Merge remote-tracking branch 'remotes/origin/development_1.0.1_net'
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/components/basys.components/basyx.components.docker/basyx.components.AASServer/pom.xml
index d73f236..dd9650c 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/pom.xml
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.docker</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.components.AASServer</artifactId>
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java
index 4d3ead9..e4205a0 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java
@@ -218,7 +218,7 @@
}
private void addSubmodelProvidersById(String smId, MultiSubmodelProvider provider) {
- ISubmodelAPI smApi = new MongoDBSubmodelAPI(smId);
+ ISubmodelAPI smApi = new MongoDBSubmodelAPI(config, smId);
SubmodelProvider smProvider = new SubmodelProvider(smApi);
provider.addSubmodel(smProvider);
}
@@ -264,7 +264,7 @@
@Override
public void deleteAAS(IIdentifier aasId) {
- Query hasId = query(where(IDPATH).is(aasId));
+ Query hasId = query(where(IDPATH).is(aasId.getId()));
mongoOps.remove(hasId, aasCollection);
aasProviderMap.remove(aasId.getId());
}
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBAggregator.java b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBAggregator.java
index 0295aa6..39d320d 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBAggregator.java
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBAggregator.java
@@ -9,10 +9,22 @@
******************************************************************************/
package org.eclipse.basyx.regression.AASServer;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
import org.eclipse.basyx.aas.aggregator.api.IAASAggregator;
+import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
import org.eclipse.basyx.components.aas.mongodb.MongoDBAASAggregator;
import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
+import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration;
import org.eclipse.basyx.testsuite.regression.aas.aggregator.AASAggregatorSuite;
+import org.junit.Test;
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+
public class TestMongoDBAggregator extends AASAggregatorSuite {
@@ -23,4 +35,43 @@
return aggregator;
}
+
+ @Test
+ public void testDeleteReachesDatabase() {
+ final BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration();
+ config.loadFromResource(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH);
+ final MongoClient client = MongoClients.create(config.getConnectionUrl());
+ final MongoTemplate mongoOps = new MongoTemplate(client, config.getDatabase());
+ final String aasCollection = config.getAASCollection();
+ final IAASAggregator aggregator = getAggregator();
+
+ // initial state: no data in the database
+ {
+ final List<AssetAdministrationShell> data = mongoOps.findAll(AssetAdministrationShell.class, aasCollection);
+ assertEquals(0, data.size());
+ }
+
+ // if we add one AAS
+ {
+ aggregator.createAAS(aas1);
+ }
+
+ // there should be that single AAS in the database
+ {
+ final List<AssetAdministrationShell> data = mongoOps.findAll(AssetAdministrationShell.class, aasCollection);
+ assertEquals(1, data.size());
+ assertEquals(aas1.getIdentification(), data.get(0).getIdentification());
+ }
+
+ // if we delete that AAS
+ {
+ aggregator.deleteAAS(aas1.getIdentification());
+ }
+
+ // there should be no AAS in the database
+ {
+ final List<AssetAdministrationShell> data = mongoOps.findAll(AssetAdministrationShell.class, aasCollection);
+ assertEquals(0, data.size());
+ }
+ }
}
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBServer.java b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBServer.java
index c014157..8e2afeb 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBServer.java
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBServer.java
@@ -12,9 +12,11 @@
import static org.junit.Assert.assertEquals;
import java.io.IOException;
+import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
+import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;
import org.eclipse.basyx.components.aas.AASServerComponent;
import org.eclipse.basyx.components.aas.configuration.AASServerBackend;
@@ -24,9 +26,11 @@
import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration;
import org.eclipse.basyx.submodel.metamodel.api.ISubmodel;
+import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
+import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -40,8 +44,12 @@
*/
public class TestMongoDBServer extends AASServerSuite {
+ private static final Identifier SM_IDENTIFICATION = new Identifier(IdentifierType.CUSTOM, "MongoDBId");
+ private static final String SM_IDSHORT = "MongoDB";
private static AASServerComponent component;
private static BaSyxMongoDBConfiguration mongoDBConfig;
+ private static BaSyxContextConfiguration contextConfig;
+ private static BaSyxAASServerConfiguration aasConfig;
@Override
protected String getURL() {
@@ -50,30 +58,66 @@
@BeforeClass
public static void setUpClass() throws ParserConfigurationException, SAXException, IOException {
- // just reset the data with this default db configuration
- new MongoDBAASAggregator(BaSyxContextConfiguration.DEFAULT_CONFIG_PATH).reset();
-
- // Setup component configuration
- BaSyxContextConfiguration contextConfig = new BaSyxContextConfiguration();
- contextConfig.loadFromResource(BaSyxContextConfiguration.DEFAULT_CONFIG_PATH);
- mongoDBConfig = new BaSyxMongoDBConfiguration();
- BaSyxAASServerConfiguration aasConfig = new BaSyxAASServerConfiguration(AASServerBackend.MONGODB, "");
-
- // Start component
+ initConfiguration();
+ resetMongoDBTestData();
component = new AASServerComponent(contextConfig, aasConfig, mongoDBConfig);
component.startComponent();
}
+ private static void resetMongoDBTestData() {
+ new MongoDBAASAggregator(mongoDBConfig).reset();
+ }
+
+ private static void initConfiguration() {
+ mongoDBConfig = new BaSyxMongoDBConfiguration();
+ mongoDBConfig.setAASCollection("basyxTestAAS");
+ mongoDBConfig.setSubmodelCollection("basyxTestSM");
+ contextConfig = new BaSyxContextConfiguration();
+ contextConfig.loadFromResource(BaSyxContextConfiguration.DEFAULT_CONFIG_PATH);
+ aasConfig = new BaSyxAASServerConfiguration(AASServerBackend.MONGODB, "");
+ }
+
@Test
public void testAddSubmodelPersistency() throws Exception {
- testAddAAS();
+ createAssetAdministrationShell();
+ createSubmodel();
- Submodel sm = new Submodel("MongoDB", new Identifier(IdentifierType.CUSTOM, "MongoDBId"));
- manager.createSubmodel(new ModelUrn(aasId), sm);
-
- MongoDBSubmodelAPI api = new MongoDBSubmodelAPI(mongoDBConfig, sm.getIdentification().getId());
+ MongoDBSubmodelAPI api = new MongoDBSubmodelAPI(mongoDBConfig, SM_IDENTIFICATION.getId());
ISubmodel persistentSM = api.getSubmodel();
- assertEquals("MongoDB", persistentSM.getIdShort());
+
+ assertEquals(SM_IDSHORT, persistentSM.getIdShort());
+ }
+
+ @Test
+ public void testAggregatorPersistency() throws Exception {
+ createAssetAdministrationShell();
+ createSubmodel();
+
+ MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig);
+ ISubmodel persistentSM = getSubmodelFromAggregator(aggregator);
+
+ assertEquals(SM_IDSHORT, persistentSM.getIdShort());
+ }
+
+ @SuppressWarnings("unchecked")
+ private ISubmodel getSubmodelFromAggregator(MongoDBAASAggregator aggregator) {
+ IModelProvider aasProvider = aggregator.getAASProvider(new ModelUrn(aasId));
+ Object smObject = aasProvider.getValue("/aas/submodels/MongoDB/submodel");
+ ISubmodel persistentSM = Submodel.createAsFacade((Map<String, Object>) smObject);
+ return persistentSM;
+ }
+
+ private void createSubmodel() {
+ Submodel sm = new Submodel(SM_IDSHORT, SM_IDENTIFICATION);
+ manager.createSubmodel(new ModelUrn(aasId), sm);
+ }
+
+ private void createAssetAdministrationShell() {
+ AssetAdministrationShell shell = new AssetAdministrationShell();
+ IIdentifier identifier = new ModelUrn(aasId);
+ shell.setIdentification(identifier);
+ shell.setIdShort("aasIdShort");
+ manager.createAAS(shell, getURL());
}
@AfterClass
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBSubmodelProvider.java b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBSubmodelProvider.java
index 6004fd0..8691ab2 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBSubmodelProvider.java
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestMongoDBSubmodelProvider.java
@@ -17,7 +17,10 @@
import org.eclipse.basyx.components.aas.mongodb.MongoDBAASAggregator;
import org.eclipse.basyx.components.aas.mongodb.MongoDBSubmodelAPI;
import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
+import org.eclipse.basyx.submodel.restapi.MultiSubmodelElementProvider;
import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
+import org.eclipse.basyx.testsuite.regression.submodel.restapi.SimpleAASSubmodel;
import org.eclipse.basyx.testsuite.regression.submodel.restapi.SubmodelProviderTest;
import org.eclipse.basyx.testsuite.regression.vab.protocol.http.TestsuiteDirectory;
import org.eclipse.basyx.vab.manager.VABConnectionManager;
@@ -55,6 +58,25 @@
}
/**
+ * Invoking operations are not supported
+ */
+ @Override
+ @Test
+ public void testOperationIdShortsWithKeywords() {
+ final String base_path = SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/keywords/";
+ VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
+ for (String keyword : SimpleAASSubmodel.KEYWORDS) {
+ Operation op = new Operation();
+ op.setIdShort(keyword + "Operation");
+
+ String path = base_path + op.getIdShort();
+ submodelElement.setValue(path, op);
+ submodelElement.getValue(path);
+ submodelElement.deleteValue(path);
+ }
+ }
+
+ /**
* Operations are not supported
*/
@Override
@@ -97,18 +119,20 @@
/**
* Now 4 instead of 8 elements
*/
+ @Override
@SuppressWarnings("unchecked")
@Test
public void testReadSubmodelElements() {
VABElementProxy submodel = getConnectionManager().connectToVABElement(submodelAddr);
Collection<Map<String, Object>> set = (Collection<Map<String, Object>>) submodel
.getValue("/submodel/submodelElements");
- assertEquals(4, set.size());
+ assertEquals(5, set.size());
}
/**
* Operations are not supported
*/
+ @Override
@Test
public void testReadSingleOperation() {
}
diff --git a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env
index dc2072c..1752555 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env
+++ b/components/basys.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env
@@ -28,7 +28,7 @@
# ##################
# The image tag of the image that is build for this component
-BASYX_IMAGE_TAG=1.0.0
+BASYX_IMAGE_TAG=1.0.1
# ##################
# Container Name
diff --git a/components/basys.components/basyx.components.docker/basyx.components.registry/pom.xml b/components/basys.components/basyx.components.docker/basyx.components.registry/pom.xml
index 0185e3f..687b470 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.registry/pom.xml
+++ b/components/basys.components/basyx.components.docker/basyx.components.registry/pom.xml
@@ -6,12 +6,12 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.docker</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.components.registry</artifactId>
<name>BaSyx Registry</name>
- <version>1.0.2</version>
+ <version>1.0.3</version>
<properties>
<basyx.components.executable>org.eclipse.basyx.components.registry.executable.RegistryExecutable</basyx.components.executable>
diff --git a/components/basys.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env b/components/basys.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env
index 36083e8..35ce24f 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env
+++ b/components/basys.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env
@@ -28,7 +28,7 @@
# ##################
# The image tag of the image that is build for this component
-BASYX_IMAGE_TAG=1.0.2
+BASYX_IMAGE_TAG=1.0.3
# ##################
# Container Name
diff --git a/components/basys.components/basyx.components.docker/pom.xml b/components/basys.components/basyx.components.docker/pom.xml
index 6afe083..afee13e 100644
--- a/components/basys.components/basyx.components.docker/pom.xml
+++ b/components/basys.components/basyx.components.docker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.components.docker</artifactId>
@@ -178,7 +178,7 @@
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.lib</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/components/basys.components/basyx.components.lib/pom.xml b/components/basys.components/basyx.components.lib/pom.xml
index 1cf5fe2..7d17605 100644
--- a/components/basys.components/basyx.components.lib/pom.xml
+++ b/components/basys.components/basyx.components.lib/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.components.lib</artifactId>
@@ -35,13 +35,13 @@
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine</artifactId>
- <version>7.12.0</version>
+ <version>7.15.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm.model</groupId>
<artifactId>camunda-bpmn-model</artifactId>
- <version>7.12.0</version>
+ <version>7.15.0</version>
</dependency>
<!-- Handles resources & files -->
<dependency>
diff --git a/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/xml/XMLAASBundleFactory.java b/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/xml/XMLAASBundleFactory.java
index 751dea4..b59e46f 100644
--- a/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/xml/XMLAASBundleFactory.java
+++ b/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/xml/XMLAASBundleFactory.java
@@ -85,7 +85,13 @@
IAsset asset = getByReference(assetRef, assets);
((AssetAdministrationShell) shell).setAsset((Asset) asset);
} catch (ResourceNotFoundException e) {
- logger.warn("Can't find asset with id " + shell.getAssetReference().getKeys().get(0).getValue() + " for AAS " + shell.getIdShort() + "; If the asset is not provided in another way, this is an error!");
+ // Enables parsing external aasx-files without any keys in assetref
+ if (shell.getAssetReference().getKeys().size() > 0) {
+ logger.warn("Can't find asset with id " + shell.getAssetReference().getKeys().get(0).getValue() + " for AAS " + shell.getIdShort() + "; If the asset is not provided in another way, this is an error!");
+ }
+ else {
+ logger.warn("Can't find asset for AAS " + shell.getIdShort() + "; If the asset is not provided in another way, this is an error!");
+ }
}
// Retrieve submodels
diff --git a/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/support/bundle/AASBundleHelper.java b/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/support/bundle/AASBundleHelper.java
index f7a48fa..37e1fd7 100644
--- a/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/support/bundle/AASBundleHelper.java
+++ b/components/basys.components/basyx.components.lib/src/main/java/org/eclipse/basyx/support/bundle/AASBundleHelper.java
@@ -17,6 +17,7 @@
import org.eclipse.basyx.aas.registration.api.IAASRegistry;
import org.eclipse.basyx.submodel.metamodel.api.ISubmodel;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
+import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
@@ -74,7 +75,7 @@
IModelProvider provider = aggregator.getAASProvider(aas.getIdentification());
for (ISubmodel sm : bundle.getSubmodels()) {
try {
- provider.getValue("/aas/submodels/" + sm.getIdShort());
+ provider.getValue("/aas/submodels/" + sm.getIdShort() + "/" + SubmodelProvider.SUBMODEL);
// If no ResourceNotFoundException occurs, SM exists on server
// -> no further action required
} catch (ResourceNotFoundException e) {
diff --git a/components/basys.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/bundle/TestAASBundleHelper.java b/components/basys.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/bundle/TestAASBundleHelper.java
index 8c28852..790494b 100644
--- a/components/basys.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/bundle/TestAASBundleHelper.java
+++ b/components/basys.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/bundle/TestAASBundleHelper.java
@@ -33,6 +33,7 @@
import org.eclipse.basyx.submodel.metamodel.facade.SubmodelElementMapCollectionConverter;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
+import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.support.bundle.AASBundle;
import org.eclipse.basyx.support.bundle.AASBundleHelper;
import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
@@ -145,7 +146,7 @@
IModelProvider provider = aggregator.getAASProvider(new Identifier(IdentifierType.CUSTOM, AAS_ID));
Submodel sm = SubmodelElementMapCollectionConverter.mapToSM(
- (Map<String, Object>) provider.getValue("/aas/submodels/" + SM_ID));
+ (Map<String, Object>) provider.getValue("/aas/submodels/" + SM_ID + "/" + SubmodelProvider.SUBMODEL));
assertEquals(SM_ID, sm.getIdentification().getId());
}
diff --git a/components/basys.components/pom.xml b/components/basys.components/pom.xml
index 6bc6bf7..727e318 100644
--- a/components/basys.components/pom.xml
+++ b/components/basys.components/pom.xml
@@ -5,7 +5,7 @@
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<name>BaSyx Components</name>
<packaging>pom</packaging>
@@ -121,14 +121,14 @@
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.sdk</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
<!-- BaSyx SDK tests -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.sdk</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
diff --git a/components/basyx.tck/basyx.tck.AASServer/pom.xml b/components/basyx.tck/basyx.tck.AASServer/pom.xml
index f4b0326..7f6cba4 100644
--- a/components/basyx.tck/basyx.tck.AASServer/pom.xml
+++ b/components/basyx.tck/basyx.tck.AASServer/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.tck</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.tck.AASServer</artifactId>
diff --git a/components/basyx.tck/basyx.tck.registry/pom.xml b/components/basyx.tck/basyx.tck.registry/pom.xml
index b609541..3100684 100644
--- a/components/basyx.tck/basyx.tck.registry/pom.xml
+++ b/components/basyx.tck/basyx.tck.registry/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.tck</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.tck.registry</artifactId>
diff --git a/components/basyx.tck/pom.xml b/components/basyx.tck/pom.xml
index 9abf62a..b82a154 100644
--- a/components/basyx.tck/pom.xml
+++ b/components/basyx.tck/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.tck</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<packaging>pom</packaging>
@@ -111,13 +111,13 @@
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.sdk</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
<!-- BaSyx SDK tests -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.sdk</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
diff --git a/examples/basys.examples/pom.xml b/examples/basys.examples/pom.xml
index e47a66e..c7ffa79 100644
--- a/examples/basys.examples/pom.xml
+++ b/examples/basys.examples/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.examples</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<packaging>jar</packaging>
<name>BaSyx Examples</name>
@@ -104,28 +104,28 @@
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.lib</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
<!-- Add explicit SQLRegistry dependency -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.registry</artifactId>
- <version>1.0.2</version>
+ <version>1.0.3</version>
</dependency>
<!-- Add explicit AAS Server component dependency -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.AASServer</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
<!-- Adds additional classes of the BaSys SDK for tests -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.sdk</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
diff --git a/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestExecuteOperation.java b/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestExecuteOperation.java
index e532841..b70fdb1 100644
--- a/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestExecuteOperation.java
+++ b/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestExecuteOperation.java
@@ -28,8 +28,9 @@
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationVariable;
-import org.eclipse.basyx.vab.protocol.http.server.BaSyxHTTPServer;
+import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext;
+import org.eclipse.basyx.vab.protocol.http.server.BaSyxHTTPServer;
import org.junit.After;
import org.junit.Test;
@@ -112,7 +113,7 @@
server.start();
IIdentifier aasIdentifier = new Identifier(IdentifierType.CUSTOM, AAS_ID);
- SubmodelDescriptor descriptor = new SubmodelDescriptor(submodel, "http://localhost:8082/submodel");
+ SubmodelDescriptor descriptor = new SubmodelDescriptor(submodel, "http://localhost:8082/submodel/" + SubmodelProvider.SUBMODEL);
// Register the new Submodel
AASRegistryProxy registry = new AASRegistryProxy(registryComponent.getRegistryPath());
diff --git a/examples/basyx.aasWrapper/pom.xml b/examples/basyx.aasWrapper/pom.xml
index 599b939..ec8231c 100644
--- a/examples/basyx.aasWrapper/pom.xml
+++ b/examples/basyx.aasWrapper/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.docker</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.components.AASWrapper</artifactId>
diff --git a/examples/basyx.aasWrapper/src/test/resources/.env b/examples/basyx.aasWrapper/src/test/resources/.env
index 4ca39a7..da08260 100644
--- a/examples/basyx.aasWrapper/src/test/resources/.env
+++ b/examples/basyx.aasWrapper/src/test/resources/.env
@@ -21,14 +21,14 @@
# ##################
# The image of the image that is build for this component
-BASYX_IMAGE_NAME=basyx/aas-wrapper
+BASYX_IMAGE_NAME=eclipsebasyx/aas-wrapper
# ##################
# Image Tag
# ##################
# The image tag of the image that is build for this component
-BASYX_IMAGE_TAG=1.0.0
+BASYX_IMAGE_TAG=1.0.1
# ##################
# Container Name
diff --git a/examples/basyx.dashboardAAS/pom.xml b/examples/basyx.dashboardAAS/pom.xml
index 183dff4..11d96a3 100644
--- a/examples/basyx.dashboardAAS/pom.xml
+++ b/examples/basyx.dashboardAAS/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.docker</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</parent>
<artifactId>basyx.components.dashboardAAS</artifactId>
diff --git a/examples/basyx.dashboardAAS/src/test/resources/.env b/examples/basyx.dashboardAAS/src/test/resources/.env
index f71a8db..5f2ef8c 100644
--- a/examples/basyx.dashboardAAS/src/test/resources/.env
+++ b/examples/basyx.dashboardAAS/src/test/resources/.env
@@ -21,14 +21,14 @@
# ##################
# The image of the image that is build for this component
-BASYX_IMAGE_NAME=basyx/dashboard-aas
+BASYX_IMAGE_NAME=eclipsebasyx/dashboard-aas
# ##################
# Image Tag
# ##################
# The image tag of the image that is build for this component
-BASYX_IMAGE_TAG=1.0.0
+BASYX_IMAGE_TAG=1.0.1
# ##################
# Container Name
diff --git a/examples/basyx.hello_world/pom.xml b/examples/basyx.hello_world/pom.xml
index d5aa122..c09f442 100644
--- a/examples/basyx.hello_world/pom.xml
+++ b/examples/basyx.hello_world/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.hello_world</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<name>BaSyx Hello World</name>
<properties>
@@ -32,21 +32,21 @@
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.lib</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
<!-- Add Registry Server component dependency -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.registry</artifactId>
- <version>1.0.2</version>
+ <version>1.0.3</version>
</dependency>
<!-- Add AAS Server component dependency -->
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.AASServer</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
</dependency>
diff --git a/examples/basyx.nodered/build.bat b/examples/basyx.nodered/build.bat
index 6e3726f..9fa90e4 100644
--- a/examples/basyx.nodered/build.bat
+++ b/examples/basyx.nodered/build.bat
@@ -1 +1 @@
-docker build -t basyx/node-red:0.1.0-SNAPSHOT .
\ No newline at end of file
+docker build -t eclipsebasyx/examples-dataflow-nodered:1.0.1 .
\ No newline at end of file
diff --git a/examples/basyx.nodered/build.sh b/examples/basyx.nodered/build.sh
index ce0a3c0..445d507 100644
--- a/examples/basyx.nodered/build.sh
+++ b/examples/basyx.nodered/build.sh
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
-docker build -t basyx/node-red:0.1.0-SNAPSHOT .
\ No newline at end of file
+docker build -t eclipsebasyx/examples-dataflow-nodered:1.0.1 .
\ No newline at end of file
diff --git a/sdks/java/basys.sdk/pom.xml b/sdks/java/basys.sdk/pom.xml
index f02c306..c72d20b 100644
--- a/sdks/java/basys.sdk/pom.xml
+++ b/sdks/java/basys.sdk/pom.xml
@@ -5,7 +5,7 @@
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.sdk</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<name>BaSyx SDK</name>
<packaging>jar</packaging>
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXFactory.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXFactory.java
index 28cf3bb..a09d971 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXFactory.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXFactory.java
@@ -15,6 +15,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
+import java.util.stream.Collectors;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
@@ -85,7 +86,7 @@
public static void buildAASX(Collection<IAssetAdministrationShell> aasList, Collection<IAsset> assetList,
Collection<IConceptDescription> conceptDescriptionList, Collection<ISubmodel> submodelList, Collection<InMemoryFile> files, OutputStream os) throws IOException, TransformerException, ParserConfigurationException {
- prepareFilePaths(submodelList);
+ prepareFilePaths(submodelList, files);
OPCPackage rootPackage = OPCPackage.create(os);
@@ -148,7 +149,11 @@
* @return UUID
*/
private static String createUniqueID() {
- return UUID.randomUUID().toString();
+ // only letters or underscore as start of id allowed
+ // https://www.w3.org/TR/1999/REC-xml-names-19990114/#ns-qualnames
+ //
+ // old AASX Package Explorer versions expect a leading R
+ return "Rid_" + UUID.randomUUID().toString();
}
/**
@@ -178,7 +183,9 @@
}
writeDataToPart(part, content);
root.registerPartAndContentType(part);
- relateTo.addRelationship(partName, TargetMode.INTERNAL, relType, createUniqueID());
+ // set TargetMode to EXTERNAL to force absolute file paths
+ // this step is necessary for compatibility reasons with AASXPackageExplorer
+ relateTo.addRelationship(partName, TargetMode.EXTERNAL, relType, createUniqueID());
return part;
}
@@ -232,13 +239,26 @@
}
/**
- * Replaces the path in all File Elements with the result of preparePath
+ * Find files which has a valid in memory file path
+ * @param elements
+ * @param inMemoryFiles
+ * @return
+ */
+ private static Collection<File> findInMemoryFileElements(Collection<ISubmodelElement> elements, Collection<InMemoryFile> inMemoryFiles) {
+ Collection<File> files = findFileElements(elements);
+ return files.stream().filter(f ->
+ isInMemoryFile(inMemoryFiles, f.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Replaces the path in File Elements which has an in memory file with the result of preparePath
*
* @param submodels the Submodels
*/
- private static void prepareFilePaths(Collection<ISubmodel> submodels) {
+ private static void prepareFilePaths(Collection<ISubmodel> submodels, Collection<InMemoryFile> inMemoryFiles) {
submodels.stream()
- .forEach(sm -> findFileElements(sm.getSubmodelElements().values()).stream().forEach(f -> f.setValue(preparePath(f.getValue()))));
+ .forEach(sm -> findInMemoryFileElements(sm.getSubmodelElements().values(), inMemoryFiles).stream().forEach(f -> f.setValue(preparePath(f.getValue()))));
}
/**
@@ -270,4 +290,20 @@
}
throw new ResourceNotFoundException("The wanted file '" + path + "' was not found in the given files.");
}
+
+ /**
+ * Finds an InMemoryFile by its path
+ *
+ * @param files the InMemoryFiles
+ * @param path the path of the wanted file
+ * @return the InMemoryFile if it was found; else null
+ */
+ private static boolean isInMemoryFile(Collection<InMemoryFile> files, String path) {
+ for(InMemoryFile file: files) {
+ if(VABPathTools.stripSlashes(file.getPath()).equals(VABPathTools.stripSlashes(path))) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXPackageExplorerConformantHelper.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXPackageExplorerConformantHelper.java
new file mode 100644
index 0000000..f6868b5
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/aasx/AASXPackageExplorerConformantHelper.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+* Copyright (C) 2021 the Eclipse BaSyx Authors
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+******************************************************************************/
+package org.eclipse.basyx.aas.factory.aasx;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.eclipse.basyx.aas.metamodel.api.IAssetAdministrationShell;
+import org.eclipse.basyx.aas.metamodel.api.parts.asset.IAsset;
+import org.eclipse.basyx.aas.metamodel.map.AasEnv;
+import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
+import org.eclipse.basyx.submodel.metamodel.api.ISubmodel;
+import org.eclipse.basyx.submodel.metamodel.api.parts.IConceptDescription;
+import org.eclipse.basyx.submodel.metamodel.api.reference.IKey;
+import org.eclipse.basyx.submodel.metamodel.api.reference.IReference;
+import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
+
+/**
+ * Helper class providing methods for handling inconsistencies in regard to
+ * BaSyx and AASXPackageExplorer
+ *
+ * @author fried
+ *
+ */
+public class AASXPackageExplorerConformantHelper {
+ /**
+ * Converts meta model elements so that the AASXPackageExplorer can load their
+ * serialized AASX
+ *
+ * @param aasList
+ * @param assetList
+ * @param conceptDescriptionList
+ * @param submodelList
+ * @return
+ */
+ public static AasEnv adapt(Collection<IAssetAdministrationShell> aasList, Collection<IAsset> assetList,
+ Collection<IConceptDescription> conceptDescriptionList, Collection<ISubmodel> submodelList) {
+
+ Collection<IAssetAdministrationShell> convertedAASs = aasList.stream()
+ .map(AASXPackageExplorerConformantHelper::removeFirstKeyFromSubmodelReferences)
+ .collect(Collectors.toList());
+
+ return new AasEnv(convertedAASs, assetList, conceptDescriptionList, submodelList);
+ }
+
+ /**
+ * Converts meta model elements so that the AASXPackageExplorer can load their
+ * serialized AASX
+ *
+ * @param env
+ * @return
+ */
+ public static AasEnv adapt(AasEnv env) {
+ return adapt(env.getAssetAdministrationShells(), env.getAssets(), env.getConceptDescriptions(),
+ env.getSubmodels());
+ }
+
+ private static IAssetAdministrationShell removeFirstKeyFromSubmodelReferences(IAssetAdministrationShell shell) {
+ Collection<IReference> convertedReferences = shell.getSubmodelReferences().stream()
+ .map(AASXPackageExplorerConformantHelper::removeFirstKeyElement).collect(Collectors.toList());
+
+ ((AssetAdministrationShell) shell).setSubmodelReferences(convertedReferences);
+
+ return shell;
+ }
+
+ private static IReference removeFirstKeyElement(IReference reference) {
+ List<IKey> keys = reference.getKeys();
+ keys.remove(0);
+
+ IReference ref = new Reference(keys);
+ return ref;
+ }
+
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/json/JSONToMetamodelConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/json/JSONToMetamodelConverter.java
index 634e67e..6bc11e9 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/json/JSONToMetamodelConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/json/JSONToMetamodelConverter.java
@@ -55,27 +55,27 @@
@SuppressWarnings("unchecked")
private AssetAdministrationShell parseAssetAdministrationShell(Object mapObject) {
- AssetAdministrationShell parsedAAS = AssetAdministrationShell.createAsFacade((Map<String, Object>) mapObject);
+ Map<String, Object> aasMap = (Map<String, Object>) mapObject;
// Fix Asset - Asset in json-Serialization is just a reference
- Map<String, Object> assetRefMap = (Map<String, Object>) parsedAAS.get(AssetAdministrationShell.ASSET);
+ Map<String, Object> assetRefMap = (Map<String, Object>) aasMap.get(AssetAdministrationShell.ASSET);
if (assetRefMap.get(Reference.KEY) == null && assetRefMap.get(Asset.KIND) != null) {
// => Is already an asset, => does not need to be fixed
- return parsedAAS;
+ return AssetAdministrationShell.createAsFacade((Map<String, Object>) mapObject);
}
- parsedAAS.put(AssetAdministrationShell.ASSETREF, assetRefMap);
+ aasMap.put(AssetAdministrationShell.ASSETREF, assetRefMap);
// Now try to find the Asset and add it to the AssetAdministrationShell
- IReference assetRef = parsedAAS.getAssetReference();
+ IReference assetRef = Reference.createAsFacade((Map<String, Object>) aasMap.get(AssetAdministrationShell.ASSETREF));
IKey lastKey = assetRef.getKeys().get(assetRef.getKeys().size() - 1);
String idValue = lastKey.getValue();
for (Asset asset : assetBuf) {
if (asset.getIdentification().getId().equals(idValue)) {
- parsedAAS.put(AssetAdministrationShell.ASSET, asset);
+ aasMap.put(AssetAdministrationShell.ASSET, asset);
break;
}
}
- return parsedAAS;
+ return AssetAdministrationShell.createAsFacade((Map<String, Object>) mapObject);
}
/**
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/xml/api/parts/AssetXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/xml/api/parts/AssetXMLConverter.java
index c152b15..9ac5757 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/xml/api/parts/AssetXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/factory/xml/api/parts/AssetXMLConverter.java
@@ -170,7 +170,7 @@
private static void buildBillOfMaterial(Document document, Element root, IAsset asset) {
IReference billOfMaterial = asset.getBillOfMaterial();
if (billOfMaterial != null) {
- Element billOfMaterialRoot = document.createElement(ASSET_IDENTIFICATION_MODEL_REF);
+ Element billOfMaterialRoot = document.createElement(ASSET_BILLOFMATERIAL);
billOfMaterialRoot.appendChild(ReferenceXMLConverter.buildReferenceXML(document, billOfMaterial));
root.appendChild(billOfMaterialRoot);
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/metamodel/map/AasEnv.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/metamodel/map/AasEnv.java
index 3cf7b51..f865d26 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/metamodel/map/AasEnv.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/metamodel/map/AasEnv.java
@@ -46,6 +46,14 @@
putAll(new ModelType(MODELTYPE));
}
+ public AasEnv(Collection<IAssetAdministrationShell> aasList, Collection<IAsset> assetList,
+ Collection<IConceptDescription> conceptDescriptionList, Collection<ISubmodel> submodelList) {
+ setAssetAdministrationShells(aasList);
+ setAssets(assetList);
+ setConceptDescriptions(conceptDescriptionList);
+ setSubmodels(submodelList);
+ }
+
/**
* Creates a AssetAdministrationShell object from a map
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/restapi/MultiSubmodelProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/restapi/MultiSubmodelProvider.java
index e2b4483..19f5d9c 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/restapi/MultiSubmodelProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/restapi/MultiSubmodelProvider.java
@@ -95,6 +95,9 @@
*/
public class MultiSubmodelProvider implements IModelProvider {
+ public static final String AAS = "aas";
+ public static final String SUBMODELS_PREFIX = VABPathTools.concatenatePaths(AAS, AssetAdministrationShell.SUBMODELS);
+
/**
* Store aas providers
*/
@@ -220,7 +223,7 @@
@SuppressWarnings("unchecked")
public void addSubmodel(SubmodelProvider modelContentProvider) {
- Submodel sm = Submodel.createAsFacade((Map<String, Object>) modelContentProvider.getValue("/"));
+ Submodel sm = Submodel.createAsFacade((Map<String, Object>) modelContentProvider.getValue("/submodel"));
addSubmodel(sm, modelContentProvider);
}
@@ -258,7 +261,7 @@
VABPathTools.checkPathForNull(path);
path = VABPathTools.stripSlashes(path);
String[] pathElements = VABPathTools.splitPath(path);
- if (pathElements.length > 0 && pathElements[0].equals("aas")) {
+ if (pathElements.length > 0 && pathElements[0].equals(AAS)) {
if (pathElements.length == 1) {
return aas_provider.getValue("");
}
@@ -272,16 +275,16 @@
// Get a model provider for the submodel in the registry
provider = getModelProvider(pathElements[2]);
}
-
+
// - Retrieve submodel or property value
- return provider.getValue(VABPathTools.buildPath(pathElements, 4));
+ return provider.getValue(VABPathTools.buildPath(pathElements, 3));
}
} else {
// Handle access to AAS
return aas_provider.getValue(VABPathTools.buildPath(pathElements, 1));
}
} else {
- return new MalformedRequestException("The request " + path + " is not allowed for this endpoint");
+ throw new MalformedRequestException("The request " + path + " is not allowed for this endpoint");
}
}
@@ -297,7 +300,7 @@
// Make a list and return all local submodels
Collection<Submodel> submodels = new HashSet<>();
for (IModelProvider submodel : submodel_providers.values()) {
- submodels.add(Submodel.createAsFacade((Map<String, Object>) submodel.getValue("")));
+ submodels.add(Submodel.createAsFacade((Map<String, Object>) submodel.getValue("/submodel")));
}
// Check for remote submodels
@@ -350,15 +353,12 @@
public void setValue(String path, Object newValue) throws ProviderException {
VABPathTools.checkPathForNull(path);
path = VABPathTools.stripSlashes(path);
- // Split path
String[] pathElements = VABPathTools.splitPath(path);
String propertyPath = VABPathTools.buildPath(pathElements, 3);
- // - Ignore first 2 elements, as it is "/aas/submodels" --> 'aas','submodels'
-
- if (path.equals("aas")) {
+ if (path.equals(AAS)) {
createAssetAdministrationShell(newValue);
- } else if (!path.startsWith("aas/submodels")) {
- throw new MalformedRequestException("Access to MultiSubmodelProvider always has to start with \"aas/submodels\", was " + path);
+ } else if (!path.startsWith(SUBMODELS_PREFIX)) {
+ throw new MalformedRequestException("Access to MultiSubmodelProvider always has to start with \"" + SUBMODELS_PREFIX + "\", was " + path);
} else if (propertyPath.isEmpty()) {
createSubmodel(newValue);
} else {
@@ -393,9 +393,12 @@
public void deleteValue(String path) throws ProviderException {
VABPathTools.checkPathForNull(path);
path = VABPathTools.stripSlashes(path);
+ if (!path.startsWith(SUBMODELS_PREFIX)) {
+ throw new MalformedRequestException("Access to MultiSubmodelProvider always has to start with \"" + SUBMODELS_PREFIX + "\", was " + path);
+ }
+
String[] pathElements = VABPathTools.splitPath(path);
String propertyPath = VABPathTools.buildPath(pathElements, 3);
- // - Ignore first 2 elements, as it is "/aas/submodels" --> 'aas','submodels'
if (pathElements.length == 3) {
// Delete Submodel from registered AAS
String smIdShort = pathElements[2];
@@ -405,8 +408,8 @@
// Delete submodel reference from aas
// TODO: This is a hack until the API is further clarified
- Submodel sm = Submodel.createAsFacade((Map<String, Object>) submodel_providers.get(smIdShort).getValue("/"));
- aas_provider.deleteValue("aas/submodels/" + sm.getIdentification().getId());
+ Submodel sm = Submodel.createAsFacade((Map<String, Object>) submodel_providers.get(smIdShort).getValue("/" + SubmodelProvider.SUBMODEL));
+ aas_provider.deleteValue(SUBMODELS_PREFIX + "/" + sm.getIdentification().getId());
// Remove submodel provider
submodel_providers.remove(smIdShort);
@@ -432,10 +435,13 @@
public Object invokeOperation(String path, Object... parameter) throws ProviderException {
VABPathTools.checkPathForNull(path);
path = VABPathTools.stripSlashes(path);
+ if (!path.startsWith(SUBMODELS_PREFIX)) {
+ throw new MalformedRequestException("Access to MultiSubmodelProvider always has to start with \"" + SUBMODELS_PREFIX + "\", was " + path);
+ }
+
String[] pathElements = VABPathTools.splitPath(path);
String operationPath = VABPathTools.buildPath(pathElements, 3);
- // - Ignore first 2 elements, as it is "/aas/submodels" --> 'aas','submodels'
- // - Invoke provider and return result
+
IModelProvider provider;
if (isSubmodelLocal(pathElements[2])) {
provider = submodel_providers.get(pathElements[2]);
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/XMLHelper.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/XMLHelper.java
index 9967865..6ed37b8 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/XMLHelper.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/XMLHelper.java
@@ -13,6 +13,11 @@
import java.util.List;
import java.util.Map;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueType;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper;
+
+import com.google.common.base.Strings;
+
/**
* A Helper class containing tools for the XML converter
*
@@ -54,4 +59,35 @@
public static String getString(Object object) {
return object instanceof String ? ((String) object).trim() : "";
}
+
+ /**
+ * adapts AASX value type to local value types
+ * @param valueType
+ * @return
+ */
+ public static ValueType convertAASXValueTypeToLocal(String valueType) {
+ // Enables parsing external aasx-files with empty type
+ if (Strings.isNullOrEmpty(valueType)) {
+ return ValueType.AnySimpleType;
+ }
+
+ // Enables parsing external aasx-files with anyURI instead of anyuri
+ else if (valueType.equals("anyURI")) {
+ return ValueType.AnyURI;
+ }
+
+ // Enables parsing external aasx-files with date instead of dateTime
+ else if (valueType.equals("date")) {
+ return ValueType.DateTime;
+ }
+
+ // Enables parsing external aasx-files with decimal instead of double
+ else if (valueType.equals("decimal")) {
+ return ValueType.Double;
+ }
+
+ else {
+ return ValueTypeHelper.fromName(valueType);
+ }
+ }
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/api/dataspecification/DataSpecificationIEC61360XMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/api/dataspecification/DataSpecificationIEC61360XMLConverter.java
index f3f52b0..b7e80c1 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/api/dataspecification/DataSpecificationIEC61360XMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/api/dataspecification/DataSpecificationIEC61360XMLConverter.java
@@ -75,11 +75,11 @@
// PreferredName - LangStrings
LangStrings preferredName = LangStringsXMLConverter
- .parseLangStrings((Map<String, Object>) contentObj.get(IEC61360_PREFERREDNAME), IEC61360_LANGSTRING);
+ .parseLangStrings(contentObj.get(IEC61360_PREFERREDNAME), IEC61360_LANGSTRING);
spec.setPreferredName(preferredName);
// ShortName - LangStrings
LangStrings shortName = LangStringsXMLConverter
- .parseLangStrings((Map<String, Object>) contentObj.get(IEC61360_SHORTNAME), IEC61360_LANGSTRING);
+ .parseLangStrings(contentObj.get(IEC61360_SHORTNAME), IEC61360_LANGSTRING);
spec.setShortName(shortName);
// Unit - String
spec.setUnit(XMLHelper.getString(contentObj.get(IEC61360_UNIT)));
@@ -94,7 +94,7 @@
spec.setDataType(DataTypeIEC61360.fromString(XMLHelper.getString(contentObj.get(IEC61360_DATATYPE))));
// Definition - LangStrings
LangStrings definition = LangStringsXMLConverter
- .parseLangStrings((Map<String, Object>) contentObj.get(IEC61360_DEFINITION), IEC61360_LANGSTRING);
+ .parseLangStrings(contentObj.get(IEC61360_DEFINITION), IEC61360_LANGSTRING);
spec.setDefinition(definition);
// ValueFormat - String
spec.setValueFormat(XMLHelper.getString(contentObj.get(IEC61360_VALUEFORMAT)));
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasDataSpecificationXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasDataSpecificationXMLConverter.java
index 9eb7956..dbf2d78 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasDataSpecificationXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasDataSpecificationXMLConverter.java
@@ -113,7 +113,7 @@
}
/**
- * Populates a given XML map with the data form a given IHasDataSpecification object<br>
+ * Populates a given XML map with the data from a given IHasDataSpecification object<br>
* Creates the <aas:embeddedDataSpecification> tag in the given root
*
* @param document the XML document
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasSemanticsXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasSemanticsXMLConverter.java
index b5ea693..4843837 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasSemanticsXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/HasSemanticsXMLConverter.java
@@ -47,7 +47,7 @@
/**
- * Populates a given XML map with the data form a given IHasSemantics object<br>
+ * Populates a given XML map with the data from a given IHasSemantics object<br>
* Creates the <aas:semanticId> tag in the given root
*
* @param document the XML document
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/IdentifiableXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/IdentifiableXMLConverter.java
index 6dd0fb5..b16ac0d 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/IdentifiableXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/IdentifiableXMLConverter.java
@@ -16,6 +16,8 @@
import org.eclipse.basyx.submodel.metamodel.api.qualifier.IIdentifiable;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.AdministrativeInformation;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -29,6 +31,7 @@
*
*/
public class IdentifiableXMLConverter {
+ private static final Logger logger = LoggerFactory.getLogger(IdentifiableXMLConverter.class);
public static final String ADMINISTRATION = "aas:administration";
public static final String VERSION = "aas:version";
@@ -53,15 +56,34 @@
}
String id = XMLHelper.getString(identierFromXML.get(XMLHelper.TEXT));
String idType = XMLHelper.getString(identierFromXML.get(IDTYPE));
- if (Strings.isNullOrEmpty(id) || Strings.isNullOrEmpty(idType)) {
- throw createInvalidIdentifierException(xmlObject);
+ if (Strings.isNullOrEmpty(id)) {
+ // Warns without exception to enable parsing external aasx-files without id
+ logger.warn("Invalid XML of Identifiable. No valid identification is present. " + xmlObject.toString());
}
+
+ if (Strings.isNullOrEmpty(idType)) {
+ // Warns without exception to enable parsing external aasx-files without idType
+ logger.warn("Invalid XML of Identifiable. empty identifierType changed to default identifierType Custom. " + xmlObject.toString());
+ idType = IdentifierType.CUSTOM.toString();
+ }
+
+ // Enables parsing external aasx-files with URI instead of IRI
+ if (idType.equalsIgnoreCase("URI")) {
+ idType = IdentifierType.IRI.toString();
+ }
+
identifiable.setIdentification(IdentifierType.fromString(idType), id);
Map<String, Object> administrationFromXML = (Map<String, Object>) xmlObject.get(ADMINISTRATION);
if(administrationFromXML != null) {
String version = XMLHelper.getString(administrationFromXML.get(VERSION));
String revision = XMLHelper.getString(administrationFromXML.get(REVISION));
+
+ // Enables parsing external aasx-files with revision and empty version
+ if (!Strings.isNullOrEmpty(revision) && Strings.isNullOrEmpty(version)) {
+ version = "0.0.1";
+ }
+
identifiable.setAdministration(new AdministrativeInformation(version, revision));
}
}
@@ -70,7 +92,7 @@
/**
- * Populates a given XML map with the data form a given IIdentifiable object<br>
+ * Populates a given XML map with the data from a given IIdentifiable object<br>
* Creates the <aas:administration> and <aas:identification> tags in the given root
*
* @param document the XML document
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/LangStringsXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/LangStringsXMLConverter.java
index e302fcc..3fc5461 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/LangStringsXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/LangStringsXMLConverter.java
@@ -42,13 +42,40 @@
}
/**
- * Parses the LangStrings object from XML with a custom lang string xml tag
+ * Parses the LangStrings object from XML/String with a custom lang string xml tag
*
- * @param xmlObject the XML map containing the <langString> tags
+ * @param obj the LangString objects or a single string
* @param tagName the custom <*langString*> tagName
* @return the parsed LangStrings object
*/
- public static LangStrings parseLangStrings(Map<String, Object> xmlObject, String tagName) {
+ @SuppressWarnings("unchecked")
+ public static LangStrings parseLangStrings(Object obj, String tagName) {
+ if (obj == null) {
+ return new LangStrings();
+ } else if (obj instanceof Map) {
+ return parseLangStringsFromMap((Map<String, Object>) obj, tagName);
+ } else {
+ return parseLangStringsFromString((String) obj);
+ }
+ }
+
+ /**
+ * Parses the LangStrings object from String description
+ * @param str given description
+ * @return parsed LangStrings object
+ */
+ private static LangStrings parseLangStringsFromString(String str) {
+ LangString langString = new LangString("EN", str);
+ return new LangStrings(langString);
+ }
+
+ /**
+ * Parses the LangStrings object from XML with a custom lang string xml tag
+ * @param xmlObject given XML object
+ * @param tagName the custom <*langString*> tagName
+ * @return the parsed LangStrings object
+ */
+ private static LangStrings parseLangStringsFromMap(Map<String, Object> xmlObject, String tagName) {
LangStrings langStrings = new LangStrings();
if(xmlObject != null) {
@@ -66,7 +93,7 @@
/**
- * Builds XML form a given LangStrings object
+ * Builds XML from a given LangStrings object
*
* @param document the XML document
* @param root the root Element where the <aas:langString> tags should be in
@@ -77,7 +104,7 @@
}
/**
- * Builds XML form a given LangStrings object with a custom langString tagName
+ * Builds XML from a given LangStrings object with a custom langString tagName
*
* @param document the XML document
* @param root the root Element where the <langString> tags should be in
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/ReferableXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/ReferableXMLConverter.java
index e4922f2..a7def92 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/ReferableXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/ReferableXMLConverter.java
@@ -14,9 +14,12 @@
import org.eclipse.basyx.submodel.factory.xml.XMLHelper;
import org.eclipse.basyx.submodel.factory.xml.converters.reference.ReferenceXMLConverter;
import org.eclipse.basyx.submodel.metamodel.api.qualifier.IReferable;
+import org.eclipse.basyx.submodel.metamodel.map.qualifier.AdministrativeInformation;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.LangStrings;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -30,6 +33,7 @@
*
*/
public class ReferableXMLConverter {
+ private static final Logger logger = LoggerFactory.getLogger(AdministrativeInformation.class);
public static final String ID_SHORT = "aas:idShort";
public static final String CATEGORY = "aas:category";
@@ -51,7 +55,8 @@
Reference parent = ReferenceXMLConverter.parseReference((Map<String, Object>) xmlObject.get(PARENT));
if (Strings.isNullOrEmpty(idShort)) {
- throw new RuntimeException("Invalid XML of Referable. No valid idShort is present. " + xmlObject.toString());
+ // Warning without exception for empty idshort for parsing external aasx-files
+ logger.warn("Invalid XML of Referable. No valid idShort is present. " + xmlObject.toString());
}
referable.setIdShort(idShort);
@@ -73,15 +78,14 @@
* @param xmlObject the XML map containing the <aas:description> tag
* @return a LangStrings Object parsed form the XML
*/
- @SuppressWarnings("unchecked")
private static LangStrings parseDescription(Map<String, Object> xmlObject) {
+ Object descObj = xmlObject.get(DESCRIPTION);
- Map<String, Object> descObj = (Map<String, Object>) xmlObject.get(DESCRIPTION);
if (descObj == null) {
return null;
}
- return LangStringsXMLConverter.parseLangStrings(descObj);
+ return LangStringsXMLConverter.parseLangStrings(descObj, LangStringsXMLConverter.LANG_STRING);
}
@@ -89,7 +93,7 @@
/**
- * Populates a given XML map with the data form a given IReferable object<br>
+ * Populates a given XML map with the data from a given IReferable object<br>
* Creates the relevant tags in the given root
*
* @param document the XML document
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/haskind/HasKindXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/haskind/HasKindXMLConverter.java
index 09a3d1f..d9e850d 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/haskind/HasKindXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/haskind/HasKindXMLConverter.java
@@ -40,13 +40,17 @@
public static void populateHasKind(Map<String, Object> xmlObject, HasKind hasKind) {
String hasKindValue = XMLHelper.getString(xmlObject.get(KIND));
if (!Strings.isNullOrEmpty(hasKindValue)) {
+ // Enables parsing external aasx-files with Type instead of Template
+ if (hasKindValue.equals("Type")) {
+ hasKindValue = ModelingKind.TEMPLATE.toString();
+ }
hasKind.setModelingKind(ModelingKind.fromString(hasKindValue));
}
}
/**
- * Populates a given XML map with the data form a given IHasKind object<br>
+ * Populates a given XML map with the data from a given IHasKind object<br>
* Creates the <aas:kind> tag in the given root
*
* @param document the XML document
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/qualifiable/QualifiableXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/qualifiable/QualifiableXMLConverter.java
index c4ab1d6..50f680d 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/qualifiable/QualifiableXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/qualifier/qualifiable/QualifiableXMLConverter.java
@@ -27,7 +27,6 @@
import org.eclipse.basyx.submodel.metamodel.map.qualifier.qualifiable.Qualifiable;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.qualifiable.Qualifier;
import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
-import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
@@ -136,7 +135,7 @@
if (valueType == null || valueType.isEmpty()) {
logger.warn("Creating element " + xmlQualifier + " without mandatory valueType!");
} else {
- qualifier.setValueType(ValueTypeHelper.fromName(valueType));
+ qualifier.setValueType(XMLHelper.convertAASXValueTypeToLocal(valueType));
}
return qualifier;
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/reference/ReferenceXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/reference/ReferenceXMLConverter.java
index 39afdad..b0c972f 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/reference/ReferenceXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/reference/ReferenceXMLConverter.java
@@ -25,6 +25,8 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import com.google.common.base.Strings;
+
/**
* Handles the conversion between an IReference object and the XML tag <aas:keys> in both directions
*
@@ -105,12 +107,26 @@
String idType = XMLHelper.getString(xmlObject.get(IDTYPE));
String type = XMLHelper.getString(xmlObject.get(TYPE));
boolean local = Boolean.parseBoolean(XMLHelper.getString(xmlObject.get(LOCAL)));
-
+
+ // Enables parsing external aasx-files with empty or null id type
+ if (Strings.isNullOrEmpty(idType)) {
+ idType = KeyType.CUSTOM.toString();
+ }
+
+ // Enables parsing external aasx-files with URI instead of IRI
+ if (idType.equalsIgnoreCase("URI")) {
+ idType = KeyType.IRI.toString();
+ }
+
+ // Enables parsing external aasx-files with empty or null key type
+ if (Strings.isNullOrEmpty(type)) {
+ type = KeyElements.REFERENCEELEMENT.toString();
+ }
return new Key(KeyElements.fromString(type), local, text, KeyType.fromString(idType));
}
/**
- * Builds XML form a given Collection of IReference objects
+ * Builds XML from a given Collection of IReference objects
*
* @param document the XML document
* @param references a Collection of IReference objects to be converted to XML
@@ -121,7 +137,7 @@
}
/**
- * Builds XML form a given Collection of IReference objects
+ * Builds XML from a given Collection of IReference objects
*
* @param document the XML document
* @param references a Collection of IReference objects to be converted to XML
@@ -146,7 +162,7 @@
/**
- * Builds XML form a given single IReference object
+ * Builds XML from a given single IReference object
*
* @param document the XML document
* @param reference the IReference object to be converted to XML
@@ -158,7 +174,7 @@
}
/**
- * Builds XML form a given single IReference object
+ * Builds XML from a given single IReference object
*
* @param document the XML document
* @param reference the IReference object to be converted to XML
@@ -174,7 +190,7 @@
}
/**
- * Builds XML form a given IKey object
+ * Builds XML from a given IKey object
*
* @param document the XML document
* @param key the IKey object to be converted to XML
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/CapabilityXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/CapabilityXMLConverter.java
new file mode 100644
index 0000000..99fa84b
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/CapabilityXMLConverter.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (C) 2021 the Eclipse BaSyx Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ******************************************************************************/
+package org.eclipse.basyx.submodel.factory.xml.converters.submodelelement;
+
+import java.util.Map;
+
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ICapability;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Parses <aas:capability> and builds the Capability object form it <br>
+ * Builds <aas:capability> from a given Capability object
+ *
+ * @author espen, fischer
+ *
+ */
+public class CapabilityXMLConverter extends SubmodelElementXMLConverter {
+
+ public static final String CAPABILITY = "aas:capability";
+
+ /**
+ * Parses a Map containing the content of XML tag <aas:capability>
+ *
+ * @param xmlObject
+ * the Map with the content of XML tag <aas:capability>
+ * @return the parsed Capability
+ */
+ public static Capability parseCapability(Map<String, Object> xmlObject) {
+ Capability capabilityMap = new Capability();
+ populateSubmodelElement(xmlObject, capabilityMap);
+ return capabilityMap;
+ }
+
+ /**
+ * Builds the <aas:capability> XML tag for a Capability
+ *
+ * @param document
+ * the XML document
+ * @param capability
+ * the ICapability to build the XML for
+ * @return the <aas:capability> XML tag for the given Capability
+ */
+ public static Element buildCapability(Document document, ICapability capability) {
+ Element xmlCapabilityRoot = document.createElement(CAPABILITY);
+
+ populateSubmodelElement(document, xmlCapabilityRoot, capability);
+
+ return xmlCapabilityRoot;
+ }
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementCollectionXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementCollectionXMLConverter.java
index 8768403..01c9d62 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementCollectionXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementCollectionXMLConverter.java
@@ -22,7 +22,7 @@
/**
* Parses <aas:submodelElementCollection> and builds the SubmodelElementCollection object from it <br>
- * Builds <aas:submodelElementCollection> form a given SubmodelElementCollection object
+ * Builds <aas:submodelElementCollection> from a given SubmodelElementCollection object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementXMLConverter.java
index 6d0545d..3b24b91 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/SubmodelElementXMLConverter.java
@@ -32,6 +32,7 @@
import org.eclipse.basyx.submodel.factory.xml.converters.submodelelement.relationship.AnnotatedRelationshipElementXMLConverter;
import org.eclipse.basyx.submodel.factory.xml.converters.submodelelement.relationship.RelationshipElementXMLConverter;
import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ICapability;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IBlob;
@@ -50,6 +51,7 @@
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.haskind.HasKind;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.qualifiable.Qualifiable;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.Blob;
@@ -133,6 +135,10 @@
xmlObject = (Map<String, Object>) xmlObject.get(BasicEventXMLConverter.BASIC_EVENT);
return BasicEventXMLConverter.parseBasicEvent(xmlObject);
}
+ else if (xmlObject.containsKey(CapabilityXMLConverter.CAPABILITY)) {
+ xmlObject = (Map<String, Object>) xmlObject.get(CapabilityXMLConverter.CAPABILITY);
+ return CapabilityXMLConverter.parseCapability(xmlObject);
+ }
else if (xmlObject.containsKey(EntityXMLConverter.ENTITY)) {
xmlObject = (Map<String, Object>) xmlObject.get(EntityXMLConverter.ENTITY);
return EntityXMLConverter.parseEntity(xmlObject);
@@ -273,6 +279,8 @@
document, (IAnnotatedRelationshipElement) submodelElement);
case Operation.MODELTYPE:
return OperationXMLConverter.buildOperation(document, (IOperation) submodelElement);
+ case Capability.MODELTYPE:
+ return CapabilityXMLConverter.buildCapability(document, (ICapability) submodelElement);
default:
return null;
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/BlobXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/BlobXMLConverter.java
index 64f7615..d3b7485 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/BlobXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/BlobXMLConverter.java
@@ -20,7 +20,7 @@
/**
* Parses <aas:blob> and builds the Blob object from it <br>
- * Builds <aas:blob> form a given Blob object
+ * Builds <aas:blob> from a given Blob object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/FileXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/FileXMLConverter.java
index 0301509..ae36ce4 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/FileXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/FileXMLConverter.java
@@ -20,7 +20,7 @@
/**
* Parses <aas:file> and builds the File object from it <br>
- * Builds <aas:file> form a given File object
+ * Builds <aas:file> from a given File object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/MultiLanguagePropertyXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/MultiLanguagePropertyXMLConverter.java
index 8b919c7..518db1e 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/MultiLanguagePropertyXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/MultiLanguagePropertyXMLConverter.java
@@ -43,8 +43,8 @@
public static MultiLanguageProperty parseMultiLanguageProperty(Map<String, Object> xmlObject) {
Map<String, Object> xmlValueId = (Map<String, Object>) xmlObject.get(VALUE_ID);
Reference valueId = ReferenceXMLConverter.parseReference(xmlValueId);
- Map<String, Object> xmlLangStrings = (Map<String, Object>) xmlObject.get(VALUE);
- LangStrings langStrings = LangStringsXMLConverter.parseLangStrings(xmlLangStrings);
+ Object xmlLangStrings = xmlObject.get(VALUE);
+ LangStrings langStrings = LangStringsXMLConverter.parseLangStrings(xmlLangStrings, LangStringsXMLConverter.LANG_STRING);
MultiLanguageProperty mLProperty = new MultiLanguageProperty(valueId, langStrings);
populateSubmodelElement(xmlObject, mLProperty);
return mLProperty;
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/PropertyXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/PropertyXMLConverter.java
index b402c72..90e6c95 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/PropertyXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/PropertyXMLConverter.java
@@ -18,7 +18,6 @@
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IProperty;
import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
-import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
@@ -57,7 +56,7 @@
Map<String, Object> xmlValueId = (Map<String, Object>) xmlObject.get(VALUE_ID);
Reference valueId = ReferenceXMLConverter.parseReference(xmlValueId);
- property.set(value, ValueTypeHelper.fromName(valueType));
+ property.set(value, XMLHelper.convertAASXValueTypeToLocal(valueType));
if(valueId != null) {
property.setValueId(valueId);
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/RangeXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/RangeXMLConverter.java
index 58fdb7c..4b93788 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/RangeXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/RangeXMLConverter.java
@@ -14,14 +14,13 @@
import org.eclipse.basyx.submodel.factory.xml.XMLHelper;
import org.eclipse.basyx.submodel.factory.xml.converters.submodelelement.SubmodelElementXMLConverter;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IRange;
-import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.range.Range;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Parses <aas:range> and builds the Range object from it <br>
- * Builds <aas:range> form a given Range object
+ * Builds <aas:range> from a given Range object
*
* @author conradi
*
@@ -43,7 +42,7 @@
String valueType = XMLHelper.getString(xmlObject.get(VALUE_TYPE));
String min = XMLHelper.getString(xmlObject.get(MIN));
String max = XMLHelper.getString(xmlObject.get(MAX));
- Range range = new Range(ValueTypeHelper.fromName(valueType), min, max);
+ Range range = new Range(XMLHelper.convertAASXValueTypeToLocal(valueType), min, max);
populateSubmodelElement(xmlObject, range);
return range;
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/ReferenceElementXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/ReferenceElementXMLConverter.java
index f51283f..c81c656 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/ReferenceElementXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/dataelement/ReferenceElementXMLConverter.java
@@ -21,7 +21,7 @@
/**
* Parses <aas:referenceElement> and builds the ReferenceElement object from it <br>
- * Builds <aas:referenceElement> form a given ReferenceElement object
+ * Builds <aas:referenceElement> from a given ReferenceElement object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/entity/EntityXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/entity/EntityXMLConverter.java
index 60a81ef..c65b3f2 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/entity/EntityXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/entity/EntityXMLConverter.java
@@ -27,7 +27,7 @@
/**
* Parses <aas:entity> and builds the Entity object from it <br>
- * Builds <aas:entity> form a given Entity object
+ * Builds <aas:entity> from a given Entity object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/event/BasicEventXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/event/BasicEventXMLConverter.java
index c8b3051..e12e750 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/event/BasicEventXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/event/BasicEventXMLConverter.java
@@ -22,7 +22,7 @@
/**
* Parses <aas:basicEvent> and builds the BasicEvent object from it <br>
- * Builds <aas:basicEvent> form a given BasicEvent object
+ * Builds <aas:basicEvent> from a given BasicEvent object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/operation/OperationXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/operation/OperationXMLConverter.java
index 890f941..e982a38 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/operation/OperationXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/operation/OperationXMLConverter.java
@@ -27,7 +27,7 @@
/**
* Parses <aas:operation> and builds the Operation object from it <br>
- * Builds <aas:operation> form a given Operation object
+ * Builds <aas:operation> from a given Operation object
*
* @author conradi
*
@@ -49,26 +49,23 @@
*/
@SuppressWarnings("unchecked")
public static Operation parseOperation(Map<String, Object> xmlObject) {
+ List<OperationVariable> inList = new ArrayList<>();
+ List<OperationVariable> outList = new ArrayList<>();
+ List<OperationVariable> inoutList = new ArrayList<>();
Map<String, Object> inObj = (Map<String, Object>) xmlObject.get(INPUT_VARIABLE);
- List<Map<String, Object>> xmlOpVars = XMLHelper.getList(inObj.get(OPERATION_VARIABLE));
- List<OperationVariable> inList = new ArrayList<>();
- for(Map<String, Object> map : xmlOpVars) {
- inList.add(parseOperationVariable(map));
+ if (inObj != null) {
+ inList = getOperationVariables(inObj);
}
Map<String, Object> outObj = (Map<String, Object>) xmlObject.get(OUTPUT_VARIABLE);
- xmlOpVars = XMLHelper.getList(outObj.get(OPERATION_VARIABLE));
- List<OperationVariable> outList = new ArrayList<>();
- for(Map<String, Object> map : xmlOpVars) {
- outList.add(parseOperationVariable(map));
+ if (outObj != null) {
+ outList = getOperationVariables(outObj);
}
Map<String, Object> inoutObj = (Map<String, Object>) xmlObject.get(INOUTPUT_VARIABLE);
- xmlOpVars = XMLHelper.getList(inoutObj.get(OPERATION_VARIABLE));
- List<OperationVariable> inoutList = new ArrayList<>();
- for(Map<String, Object> map : xmlOpVars) {
- inoutList.add(parseOperationVariable(map));
+ if (inoutObj != null) {
+ inoutList = getOperationVariables(inoutObj);
}
Operation operation = new Operation(inList, outList, inoutList, null);
@@ -156,4 +153,29 @@
return operationVariableRoot;
}
+
+ /**
+ * Gets Operation Variables In/Out/InOut from variable map
+ * @param varObj map containing variables
+ * @return List of OperationVariable
+ */
+ private static List<OperationVariable> getOperationVariables(Map<String, Object> varObj) {
+ List<OperationVariable> variableList = new ArrayList<>();
+ Object operationVarObj = varObj.get(OPERATION_VARIABLE);
+
+ //TODO: Remove after non-existing aas:operationVariable problem fixed in AAS Package Explorer
+ if (operationVarObj == null) {
+ if (varObj.get(VALUE) != null) {
+ operationVarObj = varObj;
+ }
+ }
+
+ List<Map<String, Object>> xmlOpVars = XMLHelper.getList(operationVarObj);
+
+ for(Map<String, Object> map : xmlOpVars) {
+ variableList.add(parseOperationVariable(map));
+ }
+
+ return variableList;
+ }
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/relationship/RelationshipElementXMLConverter.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/relationship/RelationshipElementXMLConverter.java
index c75c7f2..d6eaf68 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/relationship/RelationshipElementXMLConverter.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/factory/xml/converters/submodelelement/relationship/RelationshipElementXMLConverter.java
@@ -23,7 +23,7 @@
/**
* Parses <aas:relationshipElement> and builds the RelationshipElement object from it <br>
- * Builds <aas:relationshipElement> form a given RelationshipElement object
+ * Builds <aas:relationshipElement> from a given RelationshipElement object
*
* @author conradi
*
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedCapability.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedCapability.java
new file mode 100644
index 0000000..933ae09
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedCapability.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2021 the Eclipse BaSyx Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ******************************************************************************/
+package org.eclipse.basyx.submodel.metamodel.connected.submodelelement;
+
+import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ICapability;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
+import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
+
+/**
+ * "Connected" implementation of ICapability
+ *
+ * @author espen, fischer
+ *
+ */
+public class ConnectedCapability extends ConnectedSubmodelElement implements ICapability {
+
+ public ConnectedCapability(VABElementProxy proxy) {
+ super(proxy);
+ }
+
+ @Override
+ protected KeyElements getKeyElement() {
+ return KeyElements.CAPABILITY;
+ }
+
+ @Override
+ public Capability getLocalCopy() {
+ return Capability.createAsFacade(getElem()).getLocalCopy();
+ }
+
+ @Override
+ public Object getValue() {
+ throw new UnsupportedOperationException("A Capability has no value");
+ }
+
+ @Override
+ public void setValue(Object value) {
+ throw new UnsupportedOperationException("A Capability has no value");
+ }
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedSubmodelElementFactory.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedSubmodelElementFactory.java
index f0bcadd..31b7520 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedSubmodelElementFactory.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/ConnectedSubmodelElementFactory.java
@@ -31,6 +31,7 @@
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.relationship.ConnectedAnnotatedRelationshipElement;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.relationship.ConnectedRelationshipElement;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.Blob;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File;
@@ -136,6 +137,8 @@
return new ConnectedOperation(proxy);
} else if(BasicEvent.isBasicEvent(mapContent)) {
return new ConnectedBasicEvent(proxy);
+ } else if (Capability.isCapability(mapContent)) {
+ return new ConnectedCapability(proxy);
} else {
return null;
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java
index 06c615e..b4dc489 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java
@@ -12,6 +12,7 @@
import java.util.Map;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.Blob;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File;
@@ -64,6 +65,8 @@
return Operation.createAsFacade(submodelElement);
} else if (BasicEvent.isBasicEvent(submodelElement)) {
return BasicEvent.createAsFacade(submodelElement);
+ } else if (Capability.isCapability(submodelElement)) {
+ return Capability.createAsFacade(submodelElement);
} else {
throw new RuntimeException("Can not create a submodel element from given map: " + submodelElement);
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/qualifier/qualifiable/Qualifier.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/qualifier/qualifiable/Qualifier.java
index 15d91ac..41720c7 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/qualifier/qualifiable/Qualifier.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/qualifier/qualifiable/Qualifier.java
@@ -61,6 +61,7 @@
put(VALUE, ValueTypeHelper.prepareForSerialization(value));
put(VALUEID, valueId);
put(VALUETYPE, valueType);
+ putAll(new ModelType(MODELTYPE));
}
/**
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/Capability.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/Capability.java
new file mode 100644
index 0000000..88e06d1
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/Capability.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (C) 2021 the Eclipse BaSyx Authors
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ******************************************************************************/
+package org.eclipse.basyx.submodel.metamodel.map.submodelelement;
+
+import java.util.Map;
+
+import org.eclipse.basyx.aas.metamodel.exception.MetamodelConstructionException;
+import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ICapability;
+import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
+
+/**
+ * A Capability element as defined in DAAS document
+ *
+ * @author espen, fischer
+ *
+ */
+public class Capability extends SubmodelElement implements ICapability {
+
+ public static final String MODELTYPE = "Capability";
+
+ public Capability() {
+ putAll(new ModelType(MODELTYPE));
+ }
+
+ /**
+ * Constructor accepting only mandatory attribute
+ *
+ * @param idShort
+ */
+ public Capability(String idShort) {
+ super(idShort);
+
+ putAll(new ModelType(MODELTYPE));
+ }
+
+ @Override
+ protected KeyElements getKeyElement() {
+ return KeyElements.CAPABILITY;
+ }
+
+ /**
+ * Creates a Capability object from a map
+ *
+ * @param obj
+ * a Capability object as raw map
+ * @return a Capability object, that behaves like a facade for the given map
+ */
+ public static Capability createAsFacade(Map<String, Object> obj) {
+ if (obj == null) {
+ return null;
+ }
+
+ if (!isValid(obj)) {
+ throw new MetamodelConstructionException(Capability.class, obj);
+ }
+
+ Capability facade = new Capability();
+ facade.setMap(obj);
+ return facade;
+ }
+
+ /**
+ * Check whether all mandatory elements for the metamodel exist in a map
+ *
+ * @return true/false
+ */
+ public static boolean isValid(Map<String, Object> obj) {
+ return SubmodelElement.isValid(obj);
+ }
+
+ /**
+ * Returns true if the given submodel element map is recognized as a Capability
+ * element
+ */
+ public static boolean isCapability(Map<String, Object> map) {
+ String modelType = ModelType.createAsFacade(map).getName();
+ // Either model type is set or the element type specific attributes are
+ // contained (fallback)
+ return MODELTYPE.equals(modelType) || (modelType == null);
+ }
+
+ @Override
+ public Capability getLocalCopy() {
+ // Return a shallow copy
+ Capability copy = new Capability();
+ copy.putAll(this);
+ return copy;
+ }
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/dataelement/property/valuetype/ValueTypeHelper.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/dataelement/property/valuetype/ValueTypeHelper.java
index c3db504..4da0bd4 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/dataelement/property/valuetype/ValueTypeHelper.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/dataelement/property/valuetype/ValueTypeHelper.java
@@ -108,7 +108,7 @@
objectType = ValueType.YearMonthDuration;
} else if (c == QName.class) {
objectType = ValueType.QName;
- } else if (c == XMLGregorianCalendar.class) {
+ } else if (obj instanceof XMLGregorianCalendar) {
objectType = ValueType.DateTime;
} else {
throw new RuntimeException("Cannot map object " + obj + " to any PropertyValueTypeDef");
@@ -219,7 +219,7 @@
public static Object prepareForSerialization(Object value) {
if(value != null) {
Class<?> c = value.getClass();
- if (c == Duration.class || c == Period.class || c == QName.class || c == XMLGregorianCalendar.class) {
+ if (c == Duration.class || c == Period.class || c == QName.class || value instanceof XMLGregorianCalendar) {
return value.toString();
}
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/OperationProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/OperationProvider.java
index a962722..70ddcd2 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/OperationProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/OperationProvider.java
@@ -144,10 +144,13 @@
private Object createInvocationResponseFromDirectResult(InvocationRequest request, Object directResult) {
// Get SubmodelElement output template
Collection<IOperationVariable> outputs = copyOutputVariables();
- SubmodelElement outputElem = (SubmodelElement) outputs.iterator().next().getValue();
- // Set result object
- outputElem.setValue(directResult);
-
+ if(outputs.size() > 0)
+ {
+ SubmodelElement outputElem = (SubmodelElement) outputs.iterator().next().getValue();
+ // Set result object
+ outputElem.setValue(directResult);
+ };
+
// Create and return InvokationResponse
return new InvocationResponse(request.getRequestId(), new ArrayList<>(), outputs, ExecutionState.COMPLETED);
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java
index 3dcb31b..1097c1f 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java
@@ -93,9 +93,11 @@
path = VABPathTools.stripSlashes(path);
String submodelWithSlash = SUBMODEL + "/";
if (path.startsWith(submodelWithSlash)) {
- path = path.replaceFirst("submodel/", "");
+ path = path.replaceFirst(submodelWithSlash, "");
} else if (path.equals(SUBMODEL)) {
path = "";
+ } else {
+ throw new MalformedRequestException("The request " + path + " is not allowed for this endpoint. /" + SUBMODEL + " is missing");
}
path = VABPathTools.stripSlashes(path);
return path;
@@ -127,7 +129,7 @@
path = removeSMElementPrefix(path);
if (endsWithValue(splitted)) { // Request for the value of an property
- String idShortPath = path.replaceFirst(Pattern.quote("/value"), "");
+ String idShortPath = removeValueSuffix(path);
return submodelAPI.getSubmodelElementValue(idShortPath);
} else if (isInvocationListPath(splitted)) {
List<String> idShorts = getIdShorts(splitted);
@@ -163,6 +165,20 @@
return splitted[splitted.length - 1].equals(Property.VALUE);
}
+ /**
+ * Removes a trailing <code>/value</code> from the path if it exists.
+ *
+ * @param path The original path, which might or might not end on {@value Property.VALUE}.
+ * @return The new path
+ */
+ private String removeValueSuffix(String path) {
+ String suffix = "/" + Property.VALUE;
+ if (path.endsWith(suffix)) {
+ path = path.substring(0, path.length() - suffix.length());
+ }
+
+ return path;
+ }
private boolean isInvocationListPath(String[] splitted) {
return splitted.length > 2 && splitted[splitted.length - 2].equals(OperationProvider.INVOCATION_LIST);
@@ -173,11 +189,11 @@
public void setValue(String path, Object newValue) throws ProviderException {
path = removeSubmodelPrefix(path);
if (path.isEmpty()) {
- throw new MalformedRequestException("Set on \"submodel\" not supported");
+ throw new MalformedRequestException("Set on \"" + SUBMODEL + "\" not supported");
} else {
String[] splitted = VABPathTools.splitPath(path);
path = removeSMElementPrefix(path);
- String idshortPath = path.replaceFirst(Pattern.quote("/value"), "");
+ String idshortPath = removeValueSuffix(path);
if (endsWithValue(splitted)) {
submodelAPI.updateSubmodelElement(idshortPath, newValue);
} else {
@@ -215,7 +231,7 @@
throw new MalformedRequestException("Path " + path + " not supported for delete");
}
} else {
- throw new MalformedRequestException("Path \"submodel\" not supported for delete");
+ throw new MalformedRequestException("Path \"" + SUBMODEL + "\" not supported for delete");
}
}
@@ -244,7 +260,7 @@
return submodelAPI.invokeOperation(path, parameters);
}
} else {
- throw new MalformedRequestException("Given path '" + path + "' does not end in /invoke");
+ throw new MalformedRequestException("Given path '" + path + "' does not end in /" + Operation.INVOKE);
}
}
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/exception/provider/ProviderException.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/exception/provider/ProviderException.java
index 8eb45b2..7e0e3af 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/exception/provider/ProviderException.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/exception/provider/ProviderException.java
@@ -22,39 +22,16 @@
* Version information for serialized instances
*/
private static final long serialVersionUID = 1L;
-
-
- /**
- * Store message
- */
- protected String message = null;
-
-
- /**
- * Constructor
- */
+
public ProviderException(String msg) {
- // Store message
- message = msg;
- }
-
-
- public ProviderException(Exception e) {
- super(e);
+ super(msg);
}
+ public ProviderException(Throwable cause) {
+ super(cause);
+ }
public ProviderException(String message, Throwable cause) {
- super(cause);
- this.message = message;
- }
-
-
- /**
- * Return detailed message
- */
- @Override
- public String getMessage() {
- return message;
+ super(message, cause);
}
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/connector/HTTPConnector.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/connector/HTTPConnector.java
index 83f39cf..b1faddd 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/connector/HTTPConnector.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/connector/HTTPConnector.java
@@ -276,7 +276,11 @@
}
private ProviderException handleProcessingException(HttpMethod method, int statusCode) {
- return ExceptionToHTTPCodeMapper.mapToException(statusCode, "[HTTP " + method.name() + "] Failed to request " + this.address + " with mediatype " + this.mediaType);
+ if (statusCode == 0) {
+ return ExceptionToHTTPCodeMapper.mapToException(404, "[HTTP " + method.name() + "] Failed to request " + this.address + " with mediatype " + this.mediaType);
+ } else {
+ return ExceptionToHTTPCodeMapper.mapToException(statusCode, "[HTTP " + method.name() + "] Failed to request " + this.address + " with mediatype " + this.mediaType);
+ }
}
/**
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/BaSyxHTTPServer.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/BaSyxHTTPServer.java
index a5eb5cc..3364aef 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/BaSyxHTTPServer.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/BaSyxHTTPServer.java
@@ -10,6 +10,7 @@
package org.eclipse.basyx.vab.protocol.http.server;
import java.io.File;
+import java.util.EnumSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.UUID;
@@ -27,7 +28,7 @@
import org.slf4j.LoggerFactory;
/**
- * Starter Class for Apache Tomcat 8.0.53 HTTP server that adds the provided servlets and respective mappings on startup.
+ * Starter Class for Apache Tomcat HTTP server that adds the provided servlets and respective mappings on startup.
*
* @author pschorn, espen, haque
*
@@ -41,6 +42,11 @@
static {
// Enable coding of forward slash in tomcat
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
+
+ // Throw exception on startup error, unless user explicitly disables it
+ if (System.getProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE") == null) {
+ System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true");
+ }
}
/**
@@ -116,10 +122,26 @@
/**
* Starts the server in a new thread to avoid blocking the main thread
+ *
+ * <p>
+ * This method blocks until the server is up and running.
+ *
+ * <p>
+ * If an error occurs during server startup the process is aborted and the method returns immediately.
+ * {@link #hasEnded()} returns <code>true</code> in this case.
+ * <br>This behavior can be disabled by setting the system property
+ * <code>org.apache.catalina.startup.EXIT_ON_INIT_FAILURE = false</code>, for instance with the <code>-D</code>
+ * command line option when launching the JVM, or through {@link System#setProperty(String, String)} (before the
+ * first call to {@link BaSyxHTTPServer}). In this case the startup is finished regardless of any errors and
+ * subsequent calls to {@link #hasEnded()} return <code>false</code>, but the server might be left in an undefined
+ * and non-functional state.
+ *
+ * <p>
+ * TODO: Throw exception upon startup failure. This is a breaking change, so wait until next major version.
*/
public void start() {
logger.trace("Starting Tomcat.....");
-
+
Thread serverThread = new Thread(() -> {
try {
tomcat.stop();
@@ -141,20 +163,29 @@
// Keeps the server thread alive until the server is shut down
tomcat.getServer().await();
} catch (LifecycleException e) {
- logger.error("Exception in start", e);
+ logger.error("Failed to start HTTP server.", e);
+
+ synchronized (tomcat) {
+ tomcat.notifyAll();
+ }
}
});
serverThread.start();
-
+
+ // Wait until tomcat is started before returning
+ EnumSet<LifecycleState> returnStates = EnumSet.of(LifecycleState.STARTED, LifecycleState.FAILED);
synchronized (tomcat) {
try {
- tomcat.wait();
+ while (!returnStates.contains(tomcat.getServer().getState())) {
+ tomcat.wait();
+ }
} catch (InterruptedException e) {
- logger.error("Exception in start", e);
+ logger.error("Interrupted while waiting for tomcat to start. Stopping tomcat.", e);
+ shutdown();
}
}
}
-
+
/**
* This Method stops and destroys the tomcat instance. This is important since Tomcat would be already
* bound to port 8080 when new tests are run that require a start of tomcat
@@ -171,5 +202,12 @@
}
}
-
+ /**
+ * Returns a value indicating whether the server is currently running.
+ *
+ * @return <code>false</code> if the server is running, <code>true</code> otherwise.
+ */
+ public boolean hasEnded() {
+ return tomcat.getServer().getState() != LifecycleState.STARTED;
+ }
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/DefaultHostNameVerifier.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/DefaultHostNameVerifier.java
similarity index 92%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/DefaultHostNameVerifier.java
rename to sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/DefaultHostNameVerifier.java
index 7e0f876..1e2b34d 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/DefaultHostNameVerifier.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/DefaultHostNameVerifier.java
@@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
-package org.eclipse.basyx.testsuite.regression.vab.protocol.https;
+package org.eclipse.basyx.vab.protocol.https;
import javax.net.ssl.HostnameVerifier;
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/DefaultTrustManager.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/DefaultTrustManager.java
similarity index 93%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/DefaultTrustManager.java
rename to sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/DefaultTrustManager.java
index 0cee46b..ceb09e5 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/DefaultTrustManager.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/DefaultTrustManager.java
@@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
-package org.eclipse.basyx.testsuite.regression.vab.protocol.https;
+package org.eclipse.basyx.vab.protocol.https;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/HTTPSConnector.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/HTTPSConnector.java
similarity index 95%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/HTTPSConnector.java
rename to sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/HTTPSConnector.java
index 0d6bd32..c88c7b6 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/HTTPSConnector.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/HTTPSConnector.java
@@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
-package org.eclipse.basyx.testsuite.regression.vab.protocol.https;
+package org.eclipse.basyx.vab.protocol.https;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/HTTPSConnectorProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/HTTPSConnectorProvider.java
similarity index 93%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/HTTPSConnectorProvider.java
rename to sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/HTTPSConnectorProvider.java
index 3d63679..1a8e47e 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/HTTPSConnectorProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/HTTPSConnectorProvider.java
@@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
-package org.eclipse.basyx.testsuite.regression.vab.protocol.https;
+package org.eclipse.basyx.vab.protocol.https;
import org.eclipse.basyx.vab.coder.json.connector.JSONConnector;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/JerseyHttpsClientFactory.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/JerseyHttpsClientFactory.java
similarity index 84%
rename from sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/JerseyHttpsClientFactory.java
rename to sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/JerseyHttpsClientFactory.java
index 6d68d2c..a698383 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/JerseyHttpsClientFactory.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/https/JerseyHttpsClientFactory.java
@@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
-package org.eclipse.basyx.testsuite.regression.vab.protocol.https;
+package org.eclipse.basyx.vab.protocol.https;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
@@ -15,6 +15,7 @@
import javax.net.ssl.TrustManager;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
+
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
@@ -28,6 +29,7 @@
*
*/
public class JerseyHttpsClientFactory {
+ private static final String PROTOCOL = "TLSv1.2";
/**
* Returns an HTTPS client
@@ -36,7 +38,7 @@
* @throws NoSuchAlgorithmException
*/
public static Client getJerseyHTTPSClient() throws KeyManagementException, NoSuchAlgorithmException {
- SSLContext sslContext = getSslContext();
+ SSLContext sslContext = getSslContext(PROTOCOL);
HostnameVerifier allHostsValid = new DefaultHostNameVerifier();
return ClientBuilder.newBuilder()
@@ -47,14 +49,15 @@
/**
* Retrieves an SSL Context
- * with TLSv1 protocol
+ * with given protocol
+ * @param protocol
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
- private static SSLContext getSslContext() throws NoSuchAlgorithmException,
+ private static SSLContext getSslContext(String protocol) throws NoSuchAlgorithmException,
KeyManagementException {
- SSLContext sslContext = SSLContext.getInstance("TLSv1");
+ SSLContext sslContext = SSLContext.getInstance(protocol);
KeyManager[] keyManagers = null;
TrustManager[] trustManager = {new DefaultTrustManager()};
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXFactoryTest.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXFactoryTest.java
index 6a6925c..2939e97 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXFactoryTest.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXFactoryTest.java
@@ -10,6 +10,7 @@
package org.eclipse.basyx.testsuite.regression.aas.factory.aasx;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
@@ -50,6 +51,7 @@
private static final String XML_PATH = "aasx/xml/content.xml";
private static final String ORIGIN_PATH = "aasx/aasx-origin";
+ private static final String EXTERNAL_FILE_URL = "http://localhost:8080/image.png";
private AssetAdministrationShell aas;
@@ -73,7 +75,7 @@
sm1 = new Submodel("sm1", new ModelUrn("SM1_ID"));
sm2 = new Submodel("sm2", new ModelUrn("SM2_ID"));
- File file1 = new File("http://localhost:8080/image.png", "image/png");
+ File file1 = new File(EXTERNAL_FILE_URL, "image/png");
file1.setIdShort("file1");
File file2 = new File("aasx/Document/docu.pdf", "application/pdf");
file2.setIdShort("file2");
@@ -98,16 +100,12 @@
assetList.add(asset);
- byte[] content1 = {0,1,2,3,4};
- InMemoryFile file = new InMemoryFile(content1, "/image.png");
+ byte[] content1 = {5,6,7,8,9};
+ InMemoryFile file = new InMemoryFile(content1, "/aasx/Document/docu.pdf");
fileList.add(file);
- byte[] content2 = {5,6,7,8,9};
- file = new InMemoryFile(content2, "/aasx/Document/docu.pdf");
- fileList.add(file);
-
- byte[] content3 = {10,11,12,13,14};
- file = new InMemoryFile(content3, "aasx/Document/docu2.pdf");
+ byte[] content2 = {10,11,12,13,14};
+ file = new InMemoryFile(content2, "aasx/Document/docu2.pdf");
fileList.add(file);
}
@@ -158,6 +156,7 @@
assertTrue(filePaths.contains(VABPathTools.stripSlashes(file.getPath())));
}
+ assertFalse(filePaths.contains(VABPathTools.stripSlashes(EXTERNAL_FILE_URL)));
}
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXPackageExplorerConformantHelperTest.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXPackageExplorerConformantHelperTest.java
new file mode 100644
index 0000000..f5d8910
--- /dev/null
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/aasx/AASXPackageExplorerConformantHelperTest.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+* Copyright (C) 2021 the Eclipse BaSyx Authors
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+******************************************************************************/
+package org.eclipse.basyx.testsuite.regression.aas.factory.aasx;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.basyx.aas.factory.aasx.AASXPackageExplorerConformantHelper;
+import org.eclipse.basyx.aas.metamodel.api.IAssetAdministrationShell;
+import org.eclipse.basyx.aas.metamodel.api.parts.asset.AssetKind;
+import org.eclipse.basyx.aas.metamodel.map.AasEnv;
+import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
+import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId;
+import org.eclipse.basyx.aas.metamodel.map.parts.Asset;
+import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
+import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
+import org.eclipse.basyx.submodel.metamodel.api.reference.IKey;
+import org.eclipse.basyx.submodel.metamodel.api.reference.IReference;
+import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
+import org.eclipse.basyx.submodel.metamodel.map.reference.Key;
+import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
+import org.junit.Test;
+
+/**
+ *
+ * @author fried
+ *
+ */
+public class AASXPackageExplorerConformantHelperTest {
+ @Test
+ public void testRemoveAASRefInSubmodelRef() {
+ Key submodelKey = createDummySubmodelKey();
+ AssetAdministrationShell testAAS = createAASWithSingleSubmodelReferenceContainingAASKey(submodelKey);
+
+ AasEnv env = AASXPackageExplorerConformantHelper.adapt(Collections.singleton(testAAS), Collections.emptyList(),
+ Collections.emptyList(), Collections.emptyList());
+
+ assertAASKeyRemovedFromSubmodelReferences(submodelKey, env);
+ }
+
+ private Key createDummySubmodelKey() {
+ return new Key(KeyElements.SUBMODEL, false, "testSubmodel", IdentifierType.CUSTOM);
+ }
+
+ private void assertAASKeyRemovedFromSubmodelReferences(Key submodelKey, AasEnv env) {
+ Collection<IAssetAdministrationShell> convertedAASs = env.getAssetAdministrationShells();
+ assertEquals(1, convertedAASs.size());
+
+ IAssetAdministrationShell convertedAAS = convertedAASs.iterator().next();
+ Collection<IReference> convertedReferences = convertedAAS.getSubmodelReferences();
+ assertEquals(1, convertedReferences.size());
+
+ Reference expected = new Reference(submodelKey);
+ assertEquals(expected, convertedReferences.iterator().next());
+ }
+
+ private AssetAdministrationShell createAASWithSingleSubmodelReferenceContainingAASKey(Key submodelKey) {
+ AssetAdministrationShell testAAS = createDummyAAS("testAAS");
+
+ Reference submodelReference = createSubmodelReference(testAAS, submodelKey);
+
+ testAAS.addSubmodelReference(submodelReference);
+ return testAAS;
+ }
+
+ private Reference createSubmodelReference(IAssetAdministrationShell aas, Key submodelKey) {
+ Key aasKey = createDummyAASKey(aas);
+
+ List<IKey> keys = Arrays.asList(aasKey, submodelKey);
+
+ return new Reference(keys);
+ }
+
+ private AssetAdministrationShell createDummyAAS(final String aasId) {
+ return new AssetAdministrationShell("testAASIdShort", new CustomId(aasId),
+ new Asset("testAssetIdShort", new CustomId("testAsset"), AssetKind.INSTANCE));
+ }
+
+ private Key createDummyAASKey(IAssetAdministrationShell aas) {
+ IIdentifier identifier = aas.getIdentification();
+ return new Key(KeyElements.ASSETADMINISTRATIONSHELL, false, identifier.getId(), identifier.getIdType());
+ }
+}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/xml/TestXMLConverter.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/xml/TestXMLConverter.java
index 47ce3c5..6f27053 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/xml/TestXMLConverter.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/factory/xml/TestXMLConverter.java
@@ -35,9 +35,11 @@
import org.eclipse.basyx.submodel.metamodel.api.ISubmodel;
import org.eclipse.basyx.submodel.metamodel.api.dataspecification.IDataSpecificationContent;
import org.eclipse.basyx.submodel.metamodel.api.dataspecification.IEmbeddedDataSpecification;
+import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
import org.eclipse.basyx.submodel.metamodel.api.parts.IConceptDescription;
import org.eclipse.basyx.submodel.metamodel.api.qualifier.IHasDataSpecification;
+import org.eclipse.basyx.submodel.metamodel.api.qualifier.haskind.ModelingKind;
import org.eclipse.basyx.submodel.metamodel.api.qualifier.qualifiable.IConstraint;
import org.eclipse.basyx.submodel.metamodel.api.reference.IKey;
import org.eclipse.basyx.submodel.metamodel.api.reference.IReference;
@@ -45,12 +47,16 @@
import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyType;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IDataElement;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IProperty;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IRange;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.entity.EntityType;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperationVariable;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.metamodel.map.dataspecification.DataSpecificationIEC61360Content;
import org.eclipse.basyx.submodel.metamodel.map.parts.ConceptDescription;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.LangStrings;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.Blob;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File;
@@ -72,6 +78,7 @@
public class TestXMLConverter {
private String xmlInPath = "src/test/resources/aas/factory/xml/in.xml";
+ private String xmlInExternalAllowedPath = "src/test/resources/aas/factory/xml/inExternalAllowed.xml";
private XMLToMetamodelConverter converter;
@@ -142,6 +149,50 @@
checkSubmodels(converterWithoutTypes.parseSubmodels());
}
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testBuildExternalAllowedXML() throws Exception {
+ String xml = new String(Files.readAllBytes(Paths.get(xmlInExternalAllowedPath)));
+ converter = new XMLToMetamodelConverter(xml);
+ //Convert the in.xml to Objects
+ List<IAssetAdministrationShell> assetAdministrationShellList = converter.parseAAS();
+ List<IAsset> assetList = converter.parseAssets();
+ List<IConceptDescription> conceptDescriptionList = converter.parseConceptDescriptions();
+ List<ISubmodel> submodelList = converter.parseSubmodels();
+
+ IAssetAdministrationShell secondShell = assetAdministrationShellList.get(1);
+
+ assertEquals("", secondShell.getIdShort());
+ IIdentifier identifier = secondShell.getIdentification();
+ assertEquals(IdentifierType.CUSTOM, identifier.getIdType());
+ assertEquals("", identifier.getId());
+ IKey key = secondShell.getAssetReference().getKeys().get(0);
+ assertEquals(KeyElements.REFERENCEELEMENT, key.getType());
+ assertEquals(KeyType.IRI, key.getIdType());
+
+ IAsset asset = assetList.get(1);
+ assertEquals(IdentifierType.IRI, asset.getIdentification().getIdType());
+
+ IProperty property1 = submodelList.get(0).getProperties().get("rotationSpeed");
+ assertEquals(ValueType.AnySimpleType, property1.getValueType());
+
+ IProperty property2 = submodelList.get(0).getProperties().get("emptyDouble");
+ assertEquals(ValueType.AnyURI, property2.getValueType());
+
+ IProperty property3 = submodelList.get(0).getProperties().get("emptyDouble2");
+ assertEquals(ValueType.DateTime, property3.getValueType());
+
+ IRange range = Range.createAsFacade((Map<String, Object>) submodelList.get(0).getSubmodelElement("range_id"));
+ assertEquals(ValueType.Double, range.getValueType());
+
+ IOperation operation = Operation.createAsFacade((Map<String, Object>) submodelList.get(0).getSubmodelElement("operation_ID"));
+ assertEquals(ModelingKind.TEMPLATE, operation.getInOutputVariables().iterator().next().getValue().getModelingKind());
+
+ IDataSpecificationContent content = conceptDescriptionList.get(0).getEmbeddedDataSpecifications().iterator().next().getContent();
+ DataSpecificationIEC61360Content parsed = DataSpecificationIEC61360Content.createAsFacade((Map<String, Object>) content);
+ assertEquals("Only Description", parsed.getShortName().get("EN"));
+ }
+
private void checkAASs(List<IAssetAdministrationShell> aasList) {
assertEquals(2, aasList.size());
@@ -343,7 +394,7 @@
private void checkSubmodelElements(ISubmodel submodel) {
Map<String, ISubmodelElement> submodelElements = (Map<String, ISubmodelElement>)
((Map<String, Object>)submodel).get(Submodel.SUBMODELELEMENT);
- assertEquals(13, submodelElements.size());
+ assertEquals(14, submodelElements.size());
ISubmodelElement element = submodelElements.get("rotationSpeed");
assertTrue(element instanceof Property);
@@ -367,6 +418,9 @@
keys = basicEvent.getObserved().getKeys();
assertEquals(1, keys.size());
assertEquals("http://www.zvei.de/demo/submodelDefinitions/87654346", keys.get(0).getValue());
+
+ element = submodelElements.get("capability_id");
+ assertTrue(element instanceof Capability);
element = submodelElements.get("entity_id");
assertTrue(element instanceof Entity);
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/manager/TestAASHTTP.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/manager/TestAASHTTP.java
index fff8642..a4c467c 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/manager/TestAASHTTP.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/manager/TestAASHTTP.java
@@ -133,7 +133,7 @@
Map<String, ISubmodelElement> elements = sm.getSubmodelElements();
// 2 properties, 4 operations, 1 collection
- assertEquals(8, elements.size());
+ assertEquals(9, elements.size());
}
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/restapi/MultiSubmodelProviderTest.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/restapi/MultiSubmodelProviderTest.java
index 87c1b84..af618f9 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/restapi/MultiSubmodelProviderTest.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/aas/restapi/MultiSubmodelProviderTest.java
@@ -26,6 +26,7 @@
import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.testsuite.regression.submodel.restapi.SimpleAASSubmodel;
import org.eclipse.basyx.testsuite.regression.vab.manager.VABConnectionManagerStub;
+import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
import org.junit.Before;
@@ -59,10 +60,7 @@
stub.addProvider(urn, "", provider);
proxy = stub.connectToVABElement(urn);
}
-
- /**
- * Run JUnit test case
- */
+
@Test
public void invokeExceptionTest() {
// Invoke operationEx1
@@ -77,6 +75,19 @@
fail();
} catch (ProviderException e) {}
}
+
+ @Test
+ public void invalidPathPrefixInvokeTest() {
+ try {
+ proxy.invokeOperation("/aas/submodelX/SimpleAASSubmodel/submodel/submodelElements/complex/" + Operation.INVOKE, 10, 3);
+ fail();
+ } catch (MalformedRequestException e) {}
+
+ try {
+ proxy.invokeOperation("/abc/submodels/SimpleAASSubmodel/submodel/submodelElements/complex/" + Operation.INVOKE, 10, 3);
+ fail();
+ } catch (MalformedRequestException e) {}
+ }
@Test
public void invokeTest() {
@@ -93,6 +104,19 @@
getTestRunner("SimpleAASSubmodel");
}
+
+ @Test
+ public void invalidPathPrefixGetTest() {
+ try {
+ proxy.getValue("/aas/submodelX/SimpleAASSubmodel/submodel/");
+ fail();
+ } catch (MalformedRequestException e) {}
+
+ try {
+ proxy.getValue("/abc/submodel/SimpleAASSubmodel/submodel/");
+ fail();
+ } catch (MalformedRequestException e) {}
+ }
@Test
public void updateSubmodelTest() {
@@ -108,6 +132,21 @@
String newId = shell.getSubmodels().get("TestSM").getIdentification().getId();
assertEquals("TestId2", newId);
}
+
+ @Test
+ public void invalidPathPrefixSetTest() {
+ Submodel sm = new SimpleAASSubmodel("TestSM");
+ sm.setIdentification(IdentifierType.CUSTOM, "TestId");
+ try {
+ proxy.setValue("/aas/submodelX/" + sm.getIdShort(), sm);
+ fail();
+ } catch (MalformedRequestException e) {}
+
+ try {
+ proxy.setValue("/abc/submodels/" + sm.getIdShort(), sm);
+ fail();
+ } catch (MalformedRequestException e) {}
+ }
@Test
public void createDeleteSubmodelTest() {
@@ -136,6 +175,22 @@
// Expected
}
}
+
+ @Test
+ public void invalidPathPrefixDeleteTest() {
+ Submodel sm = new SimpleAASSubmodel("TestSM");
+ sm.setIdentification(IdentifierType.CUSTOM, "TestId");
+ try {
+ proxy.deleteValue("/aas/submodelX/SimpleAASSubmodel");
+ fail();
+ } catch (MalformedRequestException e) {}
+
+ try {
+ proxy.deleteValue("/aas/submodelX/SimpleAASSubmodel");
+ fail();
+ } catch (MalformedRequestException e) {}
+ }
+
private void getTestRunner(String smId) {
// Get property value
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/factory/xml/converters/submodelelement/operation/TestOperationXMLConverter.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/factory/xml/converters/submodelelement/operation/TestOperationXMLConverter.java
new file mode 100644
index 0000000..f1c1a78
--- /dev/null
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/factory/xml/converters/submodelelement/operation/TestOperationXMLConverter.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+* Copyright (C) 2021 the Eclipse BaSyx Authors
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+
+*
+* SPDX-License-Identifier: EPL-2.0
+******************************************************************************/
+
+package org.eclipse.basyx.testsuite.regression.submodel.factory.xml.converters.submodelelement.operation;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.basyx.submodel.factory.xml.converters.qualifier.ReferableXMLConverter;
+import org.eclipse.basyx.submodel.factory.xml.converters.submodelelement.operation.OperationXMLConverter;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationVariable;
+import org.junit.Test;
+
+/**
+ * This class tests {@link OperationXMLConverter}
+ * @author haque
+ *
+ */
+public class TestOperationXMLConverter {
+
+ @Test
+ public void testParseOperationWithoutVariables() {
+ String idShort = "operation_ID";
+ Map<String, Object> operationMap = new HashMap<String, Object>();
+ operationMap.put(ReferableXMLConverter.ID_SHORT, "operation_ID");
+ Operation parsedOperation = OperationXMLConverter.parseOperation(operationMap);
+ assertEquals(idShort, parsedOperation.getIdShort());
+ assertEquals(new ArrayList<OperationVariable>(), parsedOperation.getInputVariables());
+ assertEquals(new ArrayList<OperationVariable>(), parsedOperation.getOutputVariables());
+ assertEquals(new ArrayList<OperationVariable>(), parsedOperation.getInOutputVariables());
+ }
+}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/TestConnectedSubmodel.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/TestConnectedSubmodel.java
index 0c56bc7..fa79a2f 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/TestConnectedSubmodel.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/TestConnectedSubmodel.java
@@ -30,7 +30,7 @@
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationVariable;
import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.testsuite.regression.submodel.metamodel.TestSubmodelSuite;
-import org.eclipse.basyx.testsuite.regression.vab.manager.VABConnectionManagerStub;
+import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider;
import org.eclipse.basyx.vab.support.TypeDestroyer;
import org.eclipse.basyx.vab.support.TypeDestroyingProvider;
@@ -77,7 +77,7 @@
SubmodelProvider provider = new SubmodelProvider(new TypeDestroyingProvider(new VABLambdaProvider(reference)));
// Create the ConnectedSubmodel based on the manager
- submodel = new ConnectedSubmodel(new VABConnectionManagerStub(provider).connectToVABElement(""));
+ submodel = new ConnectedSubmodel(new VABElementProxy("/" + SubmodelProvider.SUBMODEL, provider));
}
/**
@@ -119,7 +119,8 @@
SubmodelProvider provider = new SubmodelProvider(new TypeDestroyingProvider(new VABLambdaProvider(reference)));
// Create the ConnectedSubmodel based on the manager
- ConnectedSubmodel cSM = new ConnectedSubmodel(new VABConnectionManagerStub(provider).connectToVABElement(""));
+ VABElementProxy smProxy = new VABElementProxy("/" + SubmodelProvider.SUBMODEL, provider);
+ ConnectedSubmodel cSM = new ConnectedSubmodel(smProxy);
Object expected = TypeDestroyer.destroyType(reference);
Object actual = cSM.getLocalCopy();
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/submodelelement/TestConnectedSubmodelElementFactory.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/submodelelement/TestConnectedSubmodelElementFactory.java
index 0cdb7b9..866c64b 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/submodelelement/TestConnectedSubmodelElementFactory.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/connected/submodelelement/TestConnectedSubmodelElementFactory.java
@@ -18,6 +18,7 @@
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IProperty;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
+import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.ConnectedCapability;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.ConnectedSubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.ConnectedSubmodelElementFactory;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.dataelement.ConnectedBlob;
@@ -30,6 +31,7 @@
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.operation.ConnectedOperation;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.relationship.ConnectedRelationshipElement;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.Capability;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.Blob;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File;
@@ -40,8 +42,8 @@
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.event.BasicEvent;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.relationship.RelationshipElement;
-import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.submodel.restapi.MultiSubmodelElementProvider;
+import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider;
import org.eclipse.basyx.vab.support.TypeDestroyingProvider;
@@ -64,6 +66,7 @@
private static final String RANGE_ID = "RangeId";
private static final String REFELEMENT_ID = "RefElementId";
private static final String BASICEVENT_ID = "BasicEventId";
+ private static final String CAPABILITY_ID = "CapabilityId";
private static final String OPERATION_ID = "OperationId";
private static final String RELELEMENT_ID = "RelElementId";
private static final String SMELEMCOLLECTION_ID = "SmElemCollectionId";
@@ -87,7 +90,8 @@
values.put(Submodel.SUBMODELELEMENT, submodelElements);
- proxy = new VABElementProxy("", new SubmodelProvider(new TypeDestroyingProvider(new VABLambdaProvider(values))));
+ proxy = new VABElementProxy("/" + SubmodelProvider.SUBMODEL,
+ new SubmodelProvider(new TypeDestroyingProvider(new VABLambdaProvider(values))));
}
/**
@@ -148,7 +152,10 @@
BasicEvent basicEvent = new BasicEvent();
basicEvent.setIdShort(BASICEVENT_ID);
ret.put(BASICEVENT_ID, basicEvent);
-
+
+ Capability capability = new Capability();
+ capability.setIdShort(CAPABILITY_ID);
+ ret.put(CAPABILITY_ID, capability);
RelationshipElement relElement = new RelationshipElement();
relElement.setIdShort(RELELEMENT_ID);
@@ -196,7 +203,7 @@
ConnectedSubmodelElementFactory.getConnectedSubmodelElements(
proxy, Submodel.SUBMODELELEMENT, Submodel.SUBMODELELEMENT);
- assertEquals(10, submodelElements.size());
+ assertEquals(11, submodelElements.size());
assertTrue(submodelElements.get(PROPERTY_ID) instanceof ConnectedProperty);
assertTrue(submodelElements.get(BLOB_ID) instanceof ConnectedBlob);
assertTrue(submodelElements.get(FILE_ID) instanceof ConnectedFile);
@@ -205,6 +212,7 @@
assertTrue(submodelElements.get(REFELEMENT_ID) instanceof ConnectedReferenceElement);
assertTrue(submodelElements.get(OPERATION_ID) instanceof ConnectedOperation);
assertTrue(submodelElements.get(BASICEVENT_ID) instanceof ConnectedBasicEvent);
+ assertTrue(submodelElements.get(CAPABILITY_ID) instanceof ConnectedCapability);
assertTrue(submodelElements.get(RELELEMENT_ID) instanceof ConnectedRelationshipElement);
assertTrue(submodelElements.get(SMELEMCOLLECTION_ID) instanceof ConnectedSubmodelElementCollection);
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/qualifier/qualifiable/TestQualifier.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/qualifier/qualifiable/TestQualifier.java
index 3b9cbad..2e2f017 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/qualifier/qualifiable/TestQualifier.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/qualifier/qualifiable/TestQualifier.java
@@ -10,10 +10,11 @@
package org.eclipse.basyx.testsuite.regression.submodel.metamodel.map.qualifier.qualifiable;
import static org.junit.Assert.assertEquals;
-
+import java.util.HashMap;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier;
+import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.qualifiable.Qualifier;
import org.eclipse.basyx.submodel.metamodel.map.reference.Reference;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueType;
@@ -95,4 +96,11 @@
qualifier.setSemanticId(reference);
assertEquals(reference, qualifier.getSemanticId());
}
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testModelType() {
+ HashMap<String, Object> modelType = (HashMap<String, Object>)qualifier.get(ModelType.MODELTYPE);
+ assertEquals(Qualifier.MODELTYPE, modelType.get(ModelType.NAME));
+ }
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/submodelelement/dataelement/property/TestProperty.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/submodelelement/dataelement/property/TestProperty.java
index 97e3270..17891dc 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/submodelelement/dataelement/property/TestProperty.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/metamodel/map/submodelelement/dataelement/property/TestProperty.java
@@ -16,10 +16,16 @@
import java.math.BigInteger;
import java.time.Duration;
import java.time.LocalDate;
+import java.time.LocalTime;
import java.time.Month;
import java.time.Period;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.Collections;
-
+import java.util.GregorianCalendar;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IdentifierType;
import org.eclipse.basyx.submodel.metamodel.api.reference.IReference;
import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyElements;
@@ -79,7 +85,7 @@
}
@Test
- public void testSet(){
+ public void testSet() throws DatatypeConfigurationException{
Property booleanProp = new Property();
Boolean isSomething = true;
booleanProp.setValue(isSomething);
@@ -111,6 +117,13 @@
bigNumberProp.setValue(bignumber);
assertEquals(bignumber, bigNumberProp.getValue());
assertEquals(ValueType.PositiveInteger, bigNumberProp.getValueType());
+
+ Property dateProp = new Property();
+ GregorianCalendar dateValue = GregorianCalendar.from(ZonedDateTime.of(birthday, LocalTime.MIDNIGHT, ZoneId.of("UTC")));
+ XMLGregorianCalendar xmlDateValue = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateValue);
+ dateProp.setValue(xmlDateValue);
+ assertEquals("1960-01-01T00:00:00.000Z", dateProp.get(Property.VALUE));
+ assertEquals(xmlDateValue, dateProp.getValue());
}
@Test
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SimpleAASSubmodel.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SimpleAASSubmodel.java
index 9257cef..c6c8949 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SimpleAASSubmodel.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SimpleAASSubmodel.java
@@ -11,6 +11,7 @@
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.function.Function;
import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;
@@ -34,6 +35,11 @@
public static final String INTPROPIDSHORT = "integerProperty";
public static final String OPERATIONSIMPLEIDSHORT = "simple";
+ public static final List<String> KEYWORDS = Collections.unmodifiableList(Arrays.asList(
+ Property.MODELTYPE, Property.VALUETYPE, Property.VALUE, Property.VALUEID,
+ Submodel.MODELTYPE, Submodel.SUBMODELELEMENT,
+ Operation.MODELTYPE, Operation.INVOKE, Operation.OUT, Operation.IN, Operation.INOUT, Operation.INVOKABLE,
+ SubmodelElementCollection.MODELTYPE, SubmodelElementCollection.ALLOWDUPLICATES, SubmodelElementCollection.ORDERED));
public SimpleAASSubmodel() {
this("SimpleAASSubmodel");
@@ -111,5 +117,10 @@
containerPropRoot.setIdShort("containerRoot");
containerPropRoot.addSubmodelElement(containerProp);
addSubmodelElement(containerPropRoot);
+
+ // Create various submodel elements with keywords in their idShorts
+ SubmodelElementCollection containerKeywords = new SubmodelElementCollection();
+ containerKeywords.setIdShort("keywords");
+ addSubmodelElement(containerKeywords);
}
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java
index 02406d0..2d2d07b 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java
@@ -20,14 +20,18 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.function.Function;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.facade.SubmodelElementMapCollectionConverter;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable;
import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueType;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
import org.eclipse.basyx.submodel.restapi.MultiSubmodelElementProvider;
import org.eclipse.basyx.submodel.restapi.OperationProvider;
import org.eclipse.basyx.submodel.restapi.SubmodelProvider;
@@ -48,6 +52,7 @@
public class SubmodelProviderTest {
private VABConnectionManager connManager;
protected static final String submodelAddr = "urn:fhg:es.iese:aas:1:1:submodel";
+ protected static final String SMPROVIDER_PATH_PREFIX = "/" + SubmodelProvider.SUBMODEL + "/";
protected VABConnectionManager getConnectionManager() {
if (connManager == null) {
@@ -63,23 +68,91 @@
}
/**
+ * Tests all basic submodel operations with idShorts composed of various keywords.
+ *
+ * <p>
+ * The test counts as successful if it finished without any exceptions thrown.
+ */
+ public void testPropertyIdShortsWithKeywords() {
+ final String base_path = SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/keywords/";
+ VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
+
+ for (String keyword : SimpleAASSubmodel.KEYWORDS) {
+ Property prop = new Property();
+ prop.setIdShort(keyword + "Property");
+ prop.setValueType(ValueType.String);
+ prop.setValue(null);
+
+ String path = base_path + prop.getIdShort();
+ submodelElement.setValue(path, prop);
+ submodelElement.getValue(path);
+ submodelElement.setValue(path + "/value", "Test");
+ submodelElement.deleteValue(path);
+ }
+ }
+
+ public void testOperationIdShortsWithKeywords() {
+ final String base_path = SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/keywords/";
+ VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
+ for (String keyword : SimpleAASSubmodel.KEYWORDS) {
+ Operation op = new Operation();
+ op.setIdShort(keyword + "Operation");
+ op.setInvokable((Function<Object[], Object>) x -> {
+ return null;
+ });
+
+ Map<String, Object> param = wrapParameter("argument", 5);
+
+ String path = base_path + op.getIdShort();
+ submodelElement.setValue(path, op);
+ submodelElement.getValue(path);
+ submodelElement.invokeOperation(path + "/invoke", param);
+ submodelElement.deleteValue(path);
+ }
+ }
+
+ @Test
+ public void testSMElementCollectionIdShortWithKeywords() {
+ final String base_path = SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/keywords/";
+ VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
+
+ for (String keyword : SimpleAASSubmodel.KEYWORDS) {
+ SubmodelElementCollection smc = new SubmodelElementCollection();
+ smc.setIdShort(keyword + "Property");
+
+ Property prop = new Property(500);
+ prop.setIdShort("testProp");
+
+ String path = base_path + smc.getIdShort();
+ submodelElement.setValue(path, smc);
+ submodelElement.setValue(path + "/" + prop.getIdShort(), prop);
+ submodelElement.getValue(path);
+ submodelElement.deleteValue(path);
+ }
+ }
+
+ /**
* Tests accessing different paths that should be supported
* @throws Exception
*/
@Test
public void testPathsRaw() throws Exception {
SubmodelProvider provider = new SubmodelProvider(new SimpleAASSubmodel("mySubmodelId"));
- provider.getValue("/submodel");
- provider.getValue("/submodel/");
+ provider.getValue("/" + SubmodelProvider.SUBMODEL);
+ provider.getValue(SMPROVIDER_PATH_PREFIX);
+ }
+ @Test
+ public void testInvalidGetPath() {
+ VABElementProxy smProxy = getConnectionManager().connectToVABElement(submodelAddr);
try {
- provider.getValue("invalid");
+ smProxy.getValue("");
fail();
- } catch (Exception e) {
-
+ } catch (MalformedRequestException e) {
}
}
+
/**
* Test creating single property
*/
@@ -90,14 +163,38 @@
// Create element
Property prop = new Property(500);
prop.setIdShort("newProperty");
- submodelElement.setValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/newProperty", prop);
+ submodelElement.setValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/newProperty", prop);
// Read back value
Integer result = (Integer) submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/newProperty/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/newProperty/value");
assertEquals(500, result.intValue());
}
+ @Test
+ public void testCreatePath() {
+ VABElementProxy smProxy = getConnectionManager().connectToVABElement(submodelAddr);
+ Property prop = new Property(500);
+ prop.setIdShort("newProperty");
+ try {
+ smProxy.createValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/newProperty", prop);
+ fail();
+ } catch (MalformedRequestException e) {
+ }
+ }
+
+ @Test
+ public void testInvalidSetPath() {
+ VABElementProxy smProxy = getConnectionManager().connectToVABElement(submodelAddr);
+ Property prop = new Property(500);
+ prop.setIdShort("newProperty");
+ try {
+ smProxy.setValue(MultiSubmodelElementProvider.ELEMENTS + "/newProperty", prop);
+ fail();
+ } catch (MalformedRequestException e) {
+ }
+ }
+
/**
* Test updating a full property
*/
@@ -107,15 +204,16 @@
// Create element
Property prop = new Property("newProperty", 500);
- submodelElement.setValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/newProperty", prop);
+ submodelElement.setValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/newProperty", prop);
// Update element
Property updatedProp = new Property("newProperty", 400);
- submodelElement.setValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/newProperty", updatedProp);
+ submodelElement.setValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/newProperty",
+ updatedProp);
// Read back value
Integer result = (Integer) submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/newProperty/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/newProperty/value");
assertEquals(400, result.intValue());
}
@@ -129,19 +227,24 @@
// Create element
Property prop = new Property(500);
prop.setIdShort("newProperty");
- submodelElement.setValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/newProperty", prop);
+ submodelElement.setValue(
+ SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/newProperty", prop);
// Read back value
Integer result = (Integer) submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/newProperty/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS
+ + "/containerRoot/newProperty/value");
assertEquals(500, result.intValue());
- submodelElement.setValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty", prop);
+ submodelElement.setValue(
+ SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty",
+ prop);
// Read back value
result = (Integer) submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS
+ + "/containerRoot/container/newProperty/value");
assertEquals(500, result.intValue());
}
@@ -152,16 +255,19 @@
// Create element
Property prop = new Property("newProperty", 500);
submodelElement.setValue(
- "/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty", prop);
+ SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty",
+ prop);
// Update element
Property prop2 = new Property("newProperty", 400);
submodelElement.setValue(
- "/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty", prop2);
+ SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty",
+ prop2);
// Read back value
Integer result = (Integer) submodelElement.getValue(
- "/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/containerRoot/container/newProperty/value");
+ SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS
+ + "/containerRoot/container/newProperty/value");
assertEquals(400, result.intValue());
}
@@ -174,34 +280,36 @@
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
// Read list of properties
- Object result = submodelElement.getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "");
+ Object result = submodelElement.getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "");
Collection<Map<String, Object>> propertySet = (Collection<Map<String, Object>>) result;
Map<String, Object> property = propertySet.stream().filter(elem -> elem.get(Identifiable.IDSHORT).equals("integerProperty")).findFirst().get();
assertEquals(123, property.get(Property.VALUE));
// Read whole property
- result = submodelElement.getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
+ result = submodelElement
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
property = (Map<String, Object>) result;
assertEquals(123, property.get(Property.VALUE));
// Read idShort
- result = submodelElement.getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/stringProperty");
+ result = submodelElement
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/stringProperty");
property = (Map<String, Object>) result;
assertEquals("stringProperty", property.get(Identifiable.IDSHORT));
// Read single value
String resString = (String) submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/stringProperty/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/stringProperty/value");
assertEquals("Test", resString);
// Read null value
Object resObject = submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/nullProperty/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/nullProperty/value");
assertEquals(null, resObject);
// Read container property
Collection<Object> resSet = (Collection<Object>) submodelElement
- .getValue("/submodel/submodelElements/containerRoot/value");
+ .getValue(SMPROVIDER_PATH_PREFIX + "submodelElements/containerRoot/value");
assertEquals(1, resSet.size());
// Get Collection from root-Collection
@@ -219,7 +327,7 @@
assertEquals(123, ((Property) containerValue.get("integerProperty")).getValue());
// Read nested property
- String pathToNestedContainer = "/submodel/submodelElements/containerRoot/container";
+ String pathToNestedContainer = SMPROVIDER_PATH_PREFIX + "submodelElements/containerRoot/container";
String pathToNestedProperty = pathToNestedContainer + "/integerProperty/";
result = submodelElement.getValue(pathToNestedProperty);
property = (Map<String, Object>) result;
@@ -235,11 +343,12 @@
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
// Update element
- submodelElement.setValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty/value", 3);
+ submodelElement
+ .setValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty/value", 3);
// Check result
Map<String, Object> result = (Map<String, Object>) submodelElement
- .getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
assertEquals(3, result.get(Property.VALUE));
}
@@ -257,7 +366,8 @@
smElements.add(newProperty);
// update value of smElemCollection
- String path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS, "containerRoot");
+ String path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
+ "containerRoot");
submodelElement.setValue(path + "/value", smElements);
// read back the collection
@@ -281,7 +391,7 @@
public void testUpdateElementInSmElementCollection() {
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
- String path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS,
+ String path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
"containerRoot", "container", "integerProperty", "value");
Integer value = (Integer) submodelElement.getValue(path);
@@ -300,11 +410,12 @@
@Test
public void testReadSingleOperation() {
VABElementProxy submodel = getConnectionManager().connectToVABElement(submodelAddr);
- Map<String, Object> operation = (Map<String, Object>) submodel.getValue("/submodel/submodelElements/simple");
+ Map<String, Object> operation = (Map<String, Object>) submodel
+ .getValue(SMPROVIDER_PATH_PREFIX + "submodelElements/simple");
assertEquals("simple", operation.get(Identifiable.IDSHORT));
try {
- submodel.getValue("/submodel/submodelElements/simple/value");
+ submodel.getValue(SMPROVIDER_PATH_PREFIX + "submodelElements/simple/value");
fail();
} catch (MalformedRequestException e) {
// An Operation has no value
@@ -318,7 +429,7 @@
@Test
public void testReadSubmodelCheckElementsInCollection() {
VABElementProxy submodel = getConnectionManager().connectToVABElement(submodelAddr);
- Map<String, Object> smMap = (Map<String, Object>) submodel.getValue("/submodel");
+ Map<String, Object> smMap = (Map<String, Object>) submodel.getValue("/" + SubmodelProvider.SUBMODEL);
Object o = smMap.get(Submodel.SUBMODELELEMENT);
assertTrue(o instanceof Collection<?>);
}
@@ -331,23 +442,32 @@
public void testReadSubmodelElements() {
VABElementProxy submodel = getConnectionManager().connectToVABElement(submodelAddr);
Collection<Map<String, Object>> set = (Collection<Map<String, Object>>) submodel
- .getValue("/submodel/submodelElements");
- assertEquals(8, set.size());
+ .getValue(SMPROVIDER_PATH_PREFIX + "submodelElements");
+ assertEquals(9, set.size());
}
- /**
- * Test deleting a single property
- */
@Test
- public void testDeleteProperty() {
+ public void testInvalidDeletePath() {
+ VABElementProxy smProxy = getConnectionManager().connectToVABElement(submodelAddr);
+ try {
+ smProxy.deleteValue(MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
+ fail();
+ } catch (MalformedRequestException e) {
+ }
+ }
+
+ @Test
+ public void testDeleteSingleProperty() {
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
// Delete property
- submodelElement.deleteValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
+ submodelElement
+ .deleteValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
// Test, if it has been deleted
try {
- submodelElement.getValue("/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
+ submodelElement
+ .getValue(SMPROVIDER_PATH_PREFIX + MultiSubmodelElementProvider.ELEMENTS + "/integerProperty");
fail();
} catch (ResourceNotFoundException e) {}
}
@@ -360,11 +480,11 @@
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
// Delete operation
- submodelElement.deleteValue("/submodel/submodelElements/simple");
+ submodelElement.deleteValue(SMPROVIDER_PATH_PREFIX + "submodelElements/simple");
// Test, if it has been deleted
try {
- submodelElement.getValue("/submodel/submodelElements/simple");
+ submodelElement.getValue(SMPROVIDER_PATH_PREFIX + "submodelElements/simple");
fail();
} catch (ResourceNotFoundException e) {}
}
@@ -376,7 +496,7 @@
public void testDeletePropertyFromCollection() {
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
- String path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS,
+ String path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
"containerRoot", "container", "integerProperty");
assertNotNull(submodelElement.getValue(path));
@@ -409,9 +529,6 @@
} catch (ResourceNotFoundException e) {}
}
- /**
- * Test invoking an operation
- */
@Test
public void testInvokeOperation() {
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
@@ -421,14 +538,25 @@
Map<String, Object> param2 = wrapParameter("SecondNumber", 2);
// Invoke operation with wrapped parameters and check result
- Object result = submodelElement.invokeOperation("/submodel/submodelElements/complex/invoke", param1, param2);
+ Object result = submodelElement.invokeOperation(SMPROVIDER_PATH_PREFIX + "submodelElements/complex/invoke",
+ param1, param2);
assertEquals(3, result);
// Invoke operation on parent element
- result = submodelElement.invokeOperation("/submodel/submodelElements/simple/invoke");
+ result = submodelElement.invokeOperation(SMPROVIDER_PATH_PREFIX + "submodelElements/simple/invoke");
assertTrue((boolean) result);
}
+ @Test
+ public void testInvalidInvokePath() {
+ VABElementProxy smProxy = getConnectionManager().connectToVABElement(submodelAddr);
+ try {
+ smProxy.invokeOperation("/submodelElements/simple/invoke" + Operation.INVOKE);
+ fail();
+ } catch (MalformedRequestException e) {
+ }
+ }
+
/**
* Test invoking an operation from within a SubmodelElementCollection
*/
@@ -436,7 +564,7 @@
public void testInvokeOperationInCollection() {
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
- String path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS,
+ String path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
"containerRoot", "container", "operationId", "invoke");
Object result = submodelElement.invokeOperation(path);
@@ -451,9 +579,9 @@
public void testGetValues() {
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
Map<String, Object> values = (Map<String, Object>) submodelElement.getValue("submodel/" + SubmodelProvider.VALUES);
-
- assertEquals(4, values.size());
-
+
+ assertEquals(5, values.size());
+
// Check if all expected Values are present
assertTrue(values.containsKey("containerRoot"));
Map<String, Object> collection1 = (Map<String, Object>) values.get("containerRoot");
@@ -475,7 +603,8 @@
VABElementProxy elementProxy = getConnectionManager().connectToVABElement(submodelAddr);
AsyncOperationHelper helper = new AsyncOperationHelper();
- String path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS, AsyncOperationHelper.ASYNC_OP_ID);
+ String path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
+ AsyncOperationHelper.ASYNC_OP_ID);
elementProxy.setValue(path, helper.getAsyncOperation());
// Wrap parameters before invoking add-operation
@@ -487,7 +616,9 @@
CallbackResponse response = CallbackResponse.createAsFacade((Map<String, Object>) elementProxy.invokeOperation(path, param1, param2));
String requestId = response.getRequestId();
- String listPath = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS, AsyncOperationHelper.ASYNC_OP_ID, OperationProvider.INVOCATION_LIST);
+ String listPath = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL,
+ MultiSubmodelElementProvider.ELEMENTS, AsyncOperationHelper.ASYNC_OP_ID,
+ OperationProvider.INVOCATION_LIST);
// Try correct operationId, wrong requestId
try {
@@ -498,7 +629,7 @@
// Try wrong operationId, correct requestId
try {
- elementProxy.getValue("/submodel/submodelElements/simple/invocationList/" + requestId);
+ elementProxy.getValue(SMPROVIDER_PATH_PREFIX + "submodelElements/simple/invocationList/" + requestId);
fail();
} catch (ResourceNotFoundException e) {
}
@@ -528,16 +659,18 @@
VABElementProxy submodelElement = getConnectionManager().connectToVABElement(submodelAddr);
AsyncOperationHelper helper = new AsyncOperationHelper();
- String path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS, AsyncOperationHelper.ASYNC_EXCEPTION_OP_ID);
+ String path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
+ AsyncOperationHelper.ASYNC_EXCEPTION_OP_ID);
submodelElement.setValue(path, helper.getAsyncExceptionOperation());
- path = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS,
+ path = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL, MultiSubmodelElementProvider.ELEMENTS,
AsyncOperationHelper.ASYNC_EXCEPTION_OP_ID, "invoke?async=true");
CallbackResponse response = (CallbackResponse) submodelElement.invokeOperation(path);
String requestId = response.getRequestId();
- String requestPath = VABPathTools.concatenatePaths("submodel", MultiSubmodelElementProvider.ELEMENTS,
+ String requestPath = VABPathTools.concatenatePaths(SubmodelProvider.SUBMODEL,
+ MultiSubmodelElementProvider.ELEMENTS,
AsyncOperationHelper.ASYNC_EXCEPTION_OP_ID, OperationProvider.INVOCATION_LIST, requestId);
// Check that it has not finished yet
@@ -561,7 +694,7 @@
}
}
- private Map<String, Object> wrapParameter(String name, Object value) {
+ protected Map<String, Object> wrapParameter(String name, Object value) {
Map<String, Object> param = new HashMap<>();
param.put(Identifiable.IDSHORT, name);
param.put(Property.VALUE, value);
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/http/TestVABHTTP.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/http/TestVABHTTP.java
index 37658c5..6a1dc45 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/http/TestVABHTTP.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/http/TestVABHTTP.java
@@ -22,8 +22,10 @@
import org.eclipse.basyx.testsuite.regression.vab.modelprovider.TestProvider;
import org.eclipse.basyx.testsuite.regression.vab.support.RecordingProvider;
+import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.eclipse.basyx.vab.manager.VABConnectionManager;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
+import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider;
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory;
import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext;
@@ -69,6 +71,16 @@
}
/**
+ * Tests, if the provider throws a ResourceNotFoundException, if the HTTP endpoint
+ * could not be reached
+ */
+ @Test(expected = ResourceNotFoundException.class)
+ public void testResourceNotFound() {
+ IModelProvider httpProvider = new HTTPConnectorFactory().getConnector("notFound");
+ httpProvider.getValue("");
+ }
+
+ /**
* Tests if multiple parameters are correctly accepted and passed to the
* provider
*/
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/TestVABHTTPS.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/TestVABHTTPS.java
index a467dd4..5191dcf 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/TestVABHTTPS.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/protocol/https/TestVABHTTPS.java
@@ -32,6 +32,8 @@
import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider;
import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext;
import org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface;
+import org.eclipse.basyx.vab.protocol.https.HTTPSConnectorProvider;
+import org.eclipse.basyx.vab.protocol.https.JerseyHttpsClientFactory;
import org.junit.Rule;
import org.junit.Test;
diff --git a/sdks/java/basys.sdk/src/test/resources/aas/factory/json/aasJsonSchemaV2.0.1_Example.json b/sdks/java/basys.sdk/src/test/resources/aas/factory/json/aasJsonSchemaV2.0.1_Example.json
index afa70e0..0acdb99 100644
--- a/sdks/java/basys.sdk/src/test/resources/aas/factory/json/aasJsonSchemaV2.0.1_Example.json
+++ b/sdks/java/basys.sdk/src/test/resources/aas/factory/json/aasJsonSchemaV2.0.1_Example.json
@@ -9,13 +9,7 @@
"value": "http://customer.com/assets/KHBVZJSQKIY",
"idType": "IRI"
}
- ],
- "kind": "Type",
- "idShort": "assetId1",
- "identification": {
- "idType": "IRI",
- "id": "assetId1"
- }
+ ]
},
"submodels": [
{
diff --git a/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/in.xml b/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/in.xml
index 31a966a..604a7fc 100644
--- a/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/in.xml
+++ b/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/in.xml
@@ -386,6 +386,11 @@
</aas:basicEvent>
</aas:submodelElement>
<aas:submodelElement>
+ <aas:capability>
+ <aas:idShort>capability_id</aas:idShort>
+ </aas:capability>
+ </aas:submodelElement>
+ <aas:submodelElement>
<aas:entity>
<aas:idShort>entity_id</aas:idShort>
<aas:assetRef>
diff --git a/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/inExternalAllowed.xml b/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/inExternalAllowed.xml
new file mode 100644
index 0000000..e36bfee
--- /dev/null
+++ b/sdks/java/basys.sdk/src/test/resources/aas/factory/xml/inExternalAllowed.xml
@@ -0,0 +1,651 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aas:aasenv xmlns:aas="http://www.admin-shell.io/aas/2/0"
+ xmlns:IEC61360="http://www.admin-shell.io/IEC61360/2/0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.admin-shell.io/aas/2/0 AAS.xsd
+ http://www.admin-shell.io/IEC61360/2/0 IEC61360.xsd">
+ <aas:assetAdministrationShells>
+ <!-- This AAS is populated with all possible fields -->
+ <aas:assetAdministrationShell>
+ <aas:idShort>asset_admin_shell</aas:idShort>
+ <aas:category>test_category</aas:category>
+ <aas:description>any String</aas:description>
+ <aas:parent>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="AssetAdministrationShell">aas_parent_id</aas:key>
+ </aas:keys>
+ </aas:parent>
+ <aas:identification idType="IRI">www.admin-shell.io/aas-sample/1/0</aas:identification>
+ <aas:administration>
+ <aas:version>1</aas:version>
+ <aas:revision>0</aas:revision>
+ </aas:administration>
+ <aas:embeddedDataSpecification>
+ <aas:dataSpecificationContent>
+ <aas:dataSpecificationIEC61360>
+ <IEC61360:preferredName>
+ <IEC61360:langString lang="DE">Drehzahl</IEC61360:langString>
+ <IEC61360:langString lang="EN">Rotation Speed</IEC61360:langString>
+ </IEC61360:preferredName>
+ <IEC61360:shortName>
+ <IEC61360:langString lang="DE">N</IEC61360:langString>
+ </IEC61360:shortName>
+ <IEC61360:unit>1/min</IEC61360:unit>
+ <IEC61360:unitId>
+ <IEC61360:keys>
+ <IEC61360:key idType="IRDI" local="false" type="GlobalReference">
+ 0173-1#05-AAA650#002
+ </IEC61360:key>
+ </IEC61360:keys>
+ </IEC61360:unitId>
+ <IEC61360:valueFormat>NR1..5</IEC61360:valueFormat>
+ </aas:dataSpecificationIEC61360>
+ </aas:dataSpecificationContent>
+ <aas:dataSpecification>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360</aas:key>
+ </aas:keys>
+ </aas:dataSpecification>
+ </aas:embeddedDataSpecification>
+ <aas:derivedFrom>
+ <aas:keys>
+ <aas:key type="ReferenceElement" local="false" idType="IRI">http://pk.festo.com/3s7plfdrs35</aas:key>
+ </aas:keys>
+ </aas:derivedFrom>
+ <aas:assetRef>
+ <aas:keys>
+ <aas:key type="Asset" local="false" idType="IRI">http://pk.festo.com/3s7plfdrs35</aas:key>
+ </aas:keys>
+ </aas:assetRef>
+ <aas:submodelRefs>
+ <aas:submodelRef>
+ <aas:keys>
+ <aas:key type="Submodel" local="true" idType="IRI">http://www.zvei.de/demo/submodel/12345679</aas:key>
+ </aas:keys>
+ </aas:submodelRef>
+ <aas:submodelRef>
+ <aas:keys>
+ <aas:key type="Submodel" local="true" idType="IRI">http://www.zvei.de/demo/submodel/12345679_2</aas:key>
+ </aas:keys>
+ </aas:submodelRef>
+ </aas:submodelRefs>
+ <aas:views>
+ <!-- This View is populated with all possible fields -->
+ <aas:view>
+ <aas:idShort>SampleView</aas:idShort>
+ <aas:category>test_categogy</aas:category>
+ <aas:description>any String</aas:description>
+ <aas:parent>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">view_parent_id</aas:key>
+ </aas:keys>
+ </aas:parent>
+ <aas:semanticId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">view_semantic_id</aas:key>
+ </aas:keys>
+ </aas:semanticId>
+ <aas:embeddedDataSpecification>
+ <aas:dataSpecificationContent>
+ <aas:dataSpecificationIEC61360>
+ <IEC61360:preferredName>
+ <IEC61360:langString lang="DE">Drehzahl</IEC61360:langString>
+ <IEC61360:langString lang="EN">Rotation Speed</IEC61360:langString>
+ </IEC61360:preferredName>
+ <IEC61360:shortName>
+ <IEC61360:langString lang="DE">N</IEC61360:langString>
+ </IEC61360:shortName>
+ <IEC61360:unit>1/min</IEC61360:unit>
+ <IEC61360:unitId>
+ <IEC61360:keys>
+ <IEC61360:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</IEC61360:key>
+ </IEC61360:keys>
+ </IEC61360:unitId>
+ <IEC61360:valueFormat>NR1..5</IEC61360:valueFormat>
+ </aas:dataSpecificationIEC61360>
+ </aas:dataSpecificationContent>
+ <aas:dataSpecification>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360</aas:key>
+ </aas:keys>
+ </aas:dataSpecification>
+ </aas:embeddedDataSpecification>
+ <aas:containedElements>
+ <aas:containedElementRef>
+ <aas:keys>
+ <aas:key type="Submodel" local="true" idType="IRI">"http://www.zvei.de/demo/submodel/12345679"</aas:key>
+ <aas:key type="Property" local="true" idType="IdShort">rotationSpeed</aas:key>
+ </aas:keys>
+ </aas:containedElementRef>
+ </aas:containedElements>
+ </aas:view>
+ <!-- This is a View with only the minimal required information in it. To test for Nullpointers and such. -->
+ <aas:view>
+ <aas:idShort>EmptyView</aas:idShort>
+ <aas:containedElements></aas:containedElements>
+ </aas:view>
+ </aas:views>
+ <aas:conceptDictionaries>
+ <aas:conceptDictionary>
+ <aas:idShort>SampleDic</aas:idShort>
+ <aas:conceptDescriptionRefs>
+ <aas:conceptDescriptionRef>
+ <aas:keys>
+ <aas:key type="ConceptDescription" local="true" idType="IRI">www.festo.com/dic/08111234</aas:key>
+ </aas:keys>
+ </aas:conceptDescriptionRef>
+ </aas:conceptDescriptionRefs>
+ </aas:conceptDictionary>
+ </aas:conceptDictionaries>
+ </aas:assetAdministrationShell>
+ <!-- This is an AAS with only the minimal required information in it. To test for Nullpointers and such. -->
+ <aas:assetAdministrationShell>
+ <aas:idShort></aas:idShort>
+ <aas:identification idType=""></aas:identification>
+ <aas:assetRef>
+ <aas:keys>
+ <aas:key type="" local="false" idType="URI">http://pk.festo.com/3s7plfdrs35</aas:key>
+ </aas:keys>
+ </aas:assetRef>
+ </aas:assetAdministrationShell>
+ </aas:assetAdministrationShells>
+ <aas:assets>
+ <!-- This Asset is populated with all possible fields -->
+ <aas:asset>
+ <aas:idShort>3s7plfdrs35_asset1</aas:idShort>
+ <aas:category>asset1_categogy</aas:category>
+ <aas:description>any String</aas:description>
+ <aas:parent>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Asset">asset_parent_id</aas:key>
+ </aas:keys>
+ </aas:parent>
+ <aas:identification idType="IRI">http://pk.festo.com/3s7plfdrs35</aas:identification>
+ <aas:administration>
+ <aas:version>1</aas:version>
+ <aas:revision>0</aas:revision>
+ </aas:administration>
+ <aas:embeddedDataSpecification>
+ <aas:dataSpecificationContent>
+ <aas:dataSpecificationIEC61360>
+ <IEC61360:preferredName>
+ <IEC61360:langString lang="DE">Drehzahl</IEC61360:langString>
+ <IEC61360:langString lang="EN">Rotation Speed</IEC61360:langString>
+ </IEC61360:preferredName>
+ <IEC61360:shortName>
+ <IEC61360:langString lang="DE">N</IEC61360:langString>
+ </IEC61360:shortName>
+ <IEC61360:unit>1/min</IEC61360:unit>
+ <IEC61360:unitId>
+ <IEC61360:keys>
+ <IEC61360:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</IEC61360:key>
+ </IEC61360:keys>
+ </IEC61360:unitId>
+ <IEC61360:valueFormat>NR1..5</IEC61360:valueFormat>
+ </aas:dataSpecificationIEC61360>
+ </aas:dataSpecificationContent>
+ <aas:dataSpecification>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360</aas:key>
+ </aas:keys>
+ </aas:dataSpecification>
+ </aas:embeddedDataSpecification>
+ <aas:assetIdentificationModelRef>
+ <aas:keys>
+ <aas:key type="ConceptDescription" local="true" idType="IRI">www.festo.com/dic/08111234</aas:key>
+ </aas:keys>
+ </aas:assetIdentificationModelRef>
+ <aas:kind>Type</aas:kind>
+ </aas:asset>
+ <aas:asset>
+ <aas:idShort>emptyAsset</aas:idShort>
+ <aas:identification idType="URI">http://pk.festo.com/q30j38dlajx</aas:identification>
+ <aas:kind>Instance</aas:kind>
+ </aas:asset>
+ </aas:assets>
+ <aas:submodels>
+ <!-- This Submodel is populated with all possible fields -->
+ <aas:submodel>
+ <aas:idShort>3s7plfdrs35_submodel1</aas:idShort>
+ <aas:category>submodel1_categogy</aas:category>
+ <aas:description>any String</aas:description>
+ <aas:parent>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">submodel_parent_id</aas:key>
+ </aas:keys>
+ </aas:parent>
+ <aas:identification idType="IRI">http://www.zvei.de/demo/submodel/12345679</aas:identification>
+ <aas:administration>
+ <aas:version>1</aas:version>
+ <aas:revision>0</aas:revision>
+ </aas:administration>
+ <aas:kind>Instance</aas:kind>
+ <aas:semanticId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:semanticId>
+ <aas:qualifier>
+ <aas:formula>
+ <aas:dependsOnRefs>
+ <aas:reference>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">qualifier_reference</aas:key>
+ </aas:keys>
+ </aas:reference>
+ </aas:dependsOnRefs>
+ </aas:formula>
+ <aas:formula>
+ <aas:dependsOnRefs>
+ <aas:reference>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">qualifier_reference2</aas:key>
+ </aas:keys>
+ </aas:reference>
+ </aas:dependsOnRefs>
+ </aas:formula>
+ <aas:qualifier>
+ <aas:valueId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:valueId>
+ <aas:value>qualifierValue</aas:value>
+ <aas:type>qualifierType</aas:type>
+ <aas:valueType></aas:valueType>
+ <aas:semanticId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:semanticId>
+ </aas:qualifier>
+ <aas:qualifier>
+ <aas:valueId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:valueId>
+ <aas:value>qualifierValue2</aas:value>
+ <aas:type>qualifierType</aas:type>
+ <aas:valueType></aas:valueType>
+ <aas:semanticId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:semanticId>
+ </aas:qualifier>
+ </aas:qualifier>
+ <aas:embeddedDataSpecification>
+ <aas:dataSpecificationContent>
+ <aas:dataSpecificationIEC61360>
+ <IEC61360:preferredName>
+ <IEC61360:langString lang="DE">Drehzahl</IEC61360:langString>
+ <IEC61360:langString lang="EN">Rotation Speed</IEC61360:langString>
+ </IEC61360:preferredName>
+ <IEC61360:shortName>
+ <IEC61360:langString lang="DE">N</IEC61360:langString>
+ </IEC61360:shortName>
+ <IEC61360:unit>1/min</IEC61360:unit>
+ <IEC61360:unitId>
+ <IEC61360:keys>
+ <IEC61360:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</IEC61360:key>
+ </IEC61360:keys>
+ </IEC61360:unitId>
+ <IEC61360:valueFormat>NR1..5</IEC61360:valueFormat>
+ </aas:dataSpecificationIEC61360>
+ </aas:dataSpecificationContent>
+ <aas:dataSpecification>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360</aas:key>
+ </aas:keys>
+ </aas:dataSpecification>
+ </aas:embeddedDataSpecification>
+ <aas:submodelElements>
+ <aas:submodelElement>
+ <aas:property>
+ <aas:idShort>rotationSpeed</aas:idShort>
+ <aas:category>VARIABLE</aas:category>
+ <aas:semanticId>
+ <aas:keys>
+ <aas:key idType="IRI" type="ConceptDescription" local="true">www.festo.com/dic/08111234</aas:key>
+ </aas:keys>
+ </aas:semanticId>
+ <aas:qualifier>
+ <aas:qualifier>
+ <aas:valueId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:valueId>
+ <aas:value>qualifierValue</aas:value>
+ <aas:type>qualifierType</aas:type>
+ <aas:valueType></aas:valueType>
+ <aas:semanticId>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:semanticId>
+ </aas:qualifier>
+ </aas:qualifier>
+ <aas:embeddedDataSpecification>
+ <aas:dataSpecificationContent>
+ <aas:dataSpecificationIEC61360>
+ <IEC61360:preferredName>
+ <IEC61360:langString lang="DE">Drehzahl</IEC61360:langString>
+ <IEC61360:langString lang="EN">Rotation Speed</IEC61360:langString>
+ </IEC61360:preferredName>
+ <IEC61360:shortName>
+ <IEC61360:langString lang="DE">N</IEC61360:langString>
+ </IEC61360:shortName>
+ <IEC61360:unit>1/min</IEC61360:unit>
+ <IEC61360:unitId>
+ <IEC61360:keys>
+ <IEC61360:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</IEC61360:key>
+ </IEC61360:keys>
+ </IEC61360:unitId>
+ <IEC61360:valueFormat>NR1..5</IEC61360:valueFormat>
+ </aas:dataSpecificationIEC61360>
+ </aas:dataSpecificationContent>
+ <aas:dataSpecification>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360</aas:key>
+ </aas:keys>
+ </aas:dataSpecification>
+ </aas:embeddedDataSpecification>
+ <aas:valueId>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</aas:key>
+ </aas:keys>
+ </aas:valueId>
+ <aas:value>2000</aas:value>
+ <aas:valueType></aas:valueType>
+ </aas:property>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:property>
+ <aas:idShort>emptyDouble</aas:idShort>
+ <aas:valueType>anyURI</aas:valueType>
+ </aas:property>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:property>
+ <aas:idShort>emptyDouble2</aas:idShort>
+ <aas:valueType>date</aas:valueType>
+ <aas:value>27-10-2009</aas:value>
+ </aas:property>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:basicEvent>
+ <aas:idShort>basic_event_id</aas:idShort>
+ <aas:observed>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:observed>
+ </aas:basicEvent>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:capability>
+ <aas:idShort>capability_id</aas:idShort>
+ </aas:capability>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:entity>
+ <aas:idShort>entity_id</aas:idShort>
+ <aas:assetRef>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="Submodel">http://www.zvei.de/demo/submodelDefinitions/87654346</aas:key>
+ </aas:keys>
+ </aas:assetRef>
+ <aas:entityType>CoManagedEntity</aas:entityType>
+ <aas:statements>
+ <!-- XML Schema currently supports only one statement, but multiple should be supported -->
+ <aas:submodelElement>
+ <aas:file>
+ <aas:idShort>file_ID</aas:idShort>
+ <aas:mimeType>file_mimetype</aas:mimeType>
+ <aas:value>file_value</aas:value>
+ </aas:file>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:range>
+ <aas:idShort>range_id</aas:idShort>
+ <aas:min>10</aas:min>
+ <aas:valueType>integer</aas:valueType>
+ </aas:range>
+ </aas:submodelElement>
+ </aas:statements>
+ </aas:entity>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:multiLanguageProperty>
+ <aas:idShort>multi_language_property_id</aas:idShort>
+ <aas:valueId>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</aas:key>
+ </aas:keys>
+ </aas:valueId>
+ <aas:value>any String</aas:value>
+ </aas:multiLanguageProperty>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:range>
+ <aas:idShort>range_id</aas:idShort>
+ <aas:max>10</aas:max>
+ <aas:min>1</aas:min>
+ <aas:valueType>decimal</aas:valueType>
+ </aas:range>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:file>
+ <aas:idShort>file_id</aas:idShort>
+ <aas:mimeType>file_mimetype</aas:mimeType>
+ <aas:value>file_value</aas:value>
+ </aas:file>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:blob>
+ <aas:idShort>blob_id</aas:idShort>
+ <aas:value>YmxvYit2YWx1ZQ==</aas:value>
+ <aas:mimeType>blob_mimetype</aas:mimeType>
+ </aas:blob>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:referenceElement>
+ <aas:idShort>reference_ELE_ID</aas:idShort>
+ <aas:value>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</aas:key>
+ </aas:keys>
+ </aas:value>
+ </aas:referenceElement>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:submodelElementCollection>
+ <aas:idShort>submodelElementCollection_ID</aas:idShort>
+ <aas:allowDuplicates>true</aas:allowDuplicates>
+ <aas:ordered>false</aas:ordered>
+ <aas:value>
+ <aas:submodelElement>
+ <aas:file>
+ <aas:idShort>file_ID</aas:idShort>
+ <aas:mimeType>file_mimetype</aas:mimeType>
+ <aas:value>file_value</aas:value>
+ </aas:file>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:blob>
+ <aas:idShort>blob_id</aas:idShort>
+ <aas:value>YmxvYit2YWx1ZQ==</aas:value>
+ <aas:mimeType>blob_mimetype</aas:mimeType>
+ </aas:blob>
+ </aas:submodelElement>
+ </aas:value>
+ </aas:submodelElementCollection>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:relationshipElement>
+ <aas:idShort>relationshipElement_ID</aas:idShort>
+ <aas:first>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#001</aas:key>
+ </aas:keys>
+ </aas:first>
+ <aas:second>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</aas:key>
+ </aas:keys>
+ </aas:second>
+ </aas:relationshipElement>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:annotatedRelationshipElement>
+ <aas:idShort>annotatedRelationshipElement_ID</aas:idShort>
+ <aas:first>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#003</aas:key>
+ </aas:keys>
+ </aas:first>
+ <aas:second>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#004</aas:key>
+ </aas:keys>
+ </aas:second>
+ <aas:annotations>
+ <aas:dataElement>
+ <aas:property>
+ <aas:idShort>prop1</aas:idShort>
+ <aas:kind>Instance</aas:kind>
+ <aas:value>1</aas:value>
+ <aas:valueType>integer</aas:valueType>
+ </aas:property>
+ </aas:dataElement>
+ <aas:dataElement>
+ <aas:property>
+ <aas:idShort>prop2</aas:idShort>
+ <aas:kind>Instance</aas:kind>
+ <aas:value>2</aas:value>
+ <aas:valueType>integer</aas:valueType>
+ </aas:property>
+ </aas:dataElement>
+ </aas:annotations>
+ </aas:annotatedRelationshipElement>
+ </aas:submodelElement>
+ <aas:submodelElement>
+ <aas:operation>
+ <aas:idShort>operation_ID</aas:idShort>
+ <aas:inoutputVariable>
+ <aas:operationVariable>
+ <aas:value>
+ <aas:referenceElement>
+ <aas:idShort>reference_ELE_ID2</aas:idShort>
+ <aas:value>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#003</aas:key>
+ </aas:keys>
+ </aas:value>
+ <aas:kind>Type</aas:kind>
+ </aas:referenceElement>
+ </aas:value>
+ </aas:operationVariable>
+ </aas:inoutputVariable>
+ <aas:inputVariable>
+ <aas:operationVariable>
+ <aas:value>
+ <aas:file>
+ <aas:idShort>file_ID</aas:idShort>
+ <aas:mimeType>file_mimetype</aas:mimeType>
+ <aas:value>file_value</aas:value>
+ <aas:kind>Template</aas:kind>
+ </aas:file>
+ </aas:value>
+ </aas:operationVariable>
+ <aas:operationVariable>
+ <aas:value>
+ <aas:blob>
+ <aas:idShort>blob_ID</aas:idShort>
+ <aas:value>YmxvYit2YWx1ZQ==</aas:value>
+ <aas:mimeType>blob_mimetype</aas:mimeType>
+ <aas:kind>Template</aas:kind>
+ </aas:blob>
+ </aas:value>
+ </aas:operationVariable>
+ </aas:inputVariable>
+ <aas:outputVariable>
+ <aas:operationVariable>
+ <aas:value>
+ <aas:referenceElement>
+ <aas:idShort>reference_ELE_ID</aas:idShort>
+ <aas:value>
+ <aas:keys>
+ <aas:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</aas:key>
+ </aas:keys>
+ </aas:value>
+ <aas:kind>Template</aas:kind>
+ </aas:referenceElement>
+ </aas:value>
+ </aas:operationVariable>
+ </aas:outputVariable>
+ </aas:operation>
+ </aas:submodelElement>
+ </aas:submodelElements>
+ </aas:submodel>
+ <!-- This is a Submodel with only the minimal required information in it. To test for Nullpointers and such. -->
+ <aas:submodel>
+ <aas:idShort>testSubmodelIdShort2</aas:idShort>
+ <aas:identification idType="IRI">http://www.zvei.de/demo/submodel/12345679</aas:identification>
+ <aas:submodelElements></aas:submodelElements>
+ </aas:submodel>
+ </aas:submodels>
+ <aas:conceptDescriptions>
+ <!-- This ConceptDescription is populated with all possible fields -->
+ <aas:conceptDescription>
+ <aas:idShort>conceptDescription1</aas:idShort>
+ <aas:category>cs_category</aas:category>
+ <aas:description>any String</aas:description>
+ <aas:parent>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="ConceptDescription">cs_parent_id</aas:key>
+ </aas:keys>
+ </aas:parent>
+ <aas:identification idType="IRI">www.festo.com/dic/08111234</aas:identification>
+ <aas:administration>
+ <aas:version>1</aas:version>
+ <aas:revision>0</aas:revision>
+ </aas:administration>
+ <aas:embeddedDataSpecification>
+ <aas:dataSpecificationContent>
+ <aas:dataSpecificationIEC61360>
+ <IEC61360:preferredName>
+ <IEC61360:langString lang="DE">Drehzahl</IEC61360:langString>
+ <IEC61360:langString lang="EN">Rotation Speed</IEC61360:langString>
+ </IEC61360:preferredName>
+ <IEC61360:shortName>Only Description</IEC61360:shortName>
+ <IEC61360:unit>1/min</IEC61360:unit>
+ <IEC61360:unitId>
+ <IEC61360:keys>
+ <IEC61360:key local="false" type="GlobalReference" idType="IRDI">0173-1#05-AAA650#002</IEC61360:key>
+ </IEC61360:keys>
+ </IEC61360:unitId>
+ <IEC61360:valueFormat>NR1..5</IEC61360:valueFormat>
+ </aas:dataSpecificationIEC61360>
+ </aas:dataSpecificationContent>
+ <aas:dataSpecification>
+ <aas:keys>
+ <aas:key idType="IRI" local="false" type="GlobalReference">www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360</aas:key>
+ </aas:keys>
+ </aas:dataSpecification>
+ </aas:embeddedDataSpecification>
+ <aas:isCaseOf>
+ <aas:keys>
+ <aas:key idType="IRI" type="ConceptDescription" local="true">www.festo.com/dic/08111234</aas:key>
+ <aas:key idType="IRI" type="ConceptDescription" local="true">www.festo.com/dic/08111234_2</aas:key>
+ </aas:keys>
+ </aas:isCaseOf>
+ </aas:conceptDescription>
+ <!-- This is a ConceptDescription with only the minimal required information in it. To test for Nullpointers and such. -->
+ <aas:conceptDescription>
+ <aas:idShort>conceptDescription2</aas:idShort>
+ <aas:identification idType="Custom">IN_emptyConceptDescription</aas:identification>
+ </aas:conceptDescription>
+ </aas:conceptDescriptions>
+</aas:aasenv>
\ No newline at end of file