diff --git a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/IDataMapper.java b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/IDataMapper.java index aee75f5485..09f9eea7db 100644 --- a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/IDataMapper.java +++ b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/IDataMapper.java @@ -16,7 +16,7 @@ public interface IDataMapper { - Output map(DataInput input); + Output map(DataInput input, MappingContext context); static DataMapperBuilder newBuilder() { return new DataMapperBuilder(); diff --git a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingContext.java b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingContext.java new file mode 100644 index 0000000000..3573ee01d3 --- /dev/null +++ b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingContext.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2015-2016 Bosch Software Innovations GmbH and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * The Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Bosch Software Innovations GmbH - Please refer to git log + */ +package org.eclipse.vorto.service.mapping; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * A Mapping Context contains further configuration attributes that are processed during the mapping + * + */ +public class MappingContext { + + private Set properties = null; + + /** + * Empty Mapping Context tries to map all function block properties of the information model + * @return new Mapping Context holding the configuration + */ + public static MappingContext empty() { + return new EmptyContext(); + } + + /** + * adds the functionblock properties that ought to be mapped by the mapping engine. + * @param propertyNames the names of the function block properties of the Information Model + * @return new Mapping Context holding the configuration + */ + public static MappingContext functionblockProperties(String...propertyNames) { + return new MappingContext(new HashSet<>(Arrays.asList(propertyNames))); + } + + protected MappingContext(Set properties) { + this.properties = properties; + } + + public boolean isIncluded(String property) { + return properties.contains(property); + } + + private static class EmptyContext extends MappingContext { + + protected EmptyContext() { + super(null); + } + + @Override + public boolean isIncluded(String property) { + return true; + } + } +} diff --git a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingSpecificationBuilder.java b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingSpecificationBuilder.java index 03bb6325bc..3758f92b7c 100644 --- a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingSpecificationBuilder.java +++ b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/MappingSpecificationBuilder.java @@ -14,6 +14,8 @@ */ package org.eclipse.vorto.service.mapping; +import java.util.Optional; + import org.eclipse.vorto.repository.api.ModelId; import org.eclipse.vorto.service.mapping.spec.RemoteMappingSpecification; @@ -22,24 +24,37 @@ public class MappingSpecificationBuilder { private ModelId modelId; private String key; private String endpoint = "http://vorto.eclipse.org"; + private String proxyHost = null; + private int proxyPort = 8080; public MappingSpecificationBuilder modelId(String infoModelId) { this.modelId = ModelId.fromPrettyFormat(infoModelId); + this.key = calculateKey(infoModelId); return this; } + + private static String calculateKey(String modelId) { + return modelId.replace(".", "_").replace(":", "_"); + } public MappingSpecificationBuilder endpoint(String endpoint) { this.endpoint = endpoint; return this; } + public MappingSpecificationBuilder proxy(String proxyHost, int proxyPort) { + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + return this; + } + public MappingSpecificationBuilder key(String key) { this.key = key; return this; } public IMappingSpecification build() { - return new RemoteMappingSpecification(this.modelId, key, endpoint); + return new RemoteMappingSpecification(this.modelId, key, endpoint,Optional.ofNullable(proxyHost),Optional.ofNullable(proxyPort)); } } diff --git a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/ditto/DittoMapper.java b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/ditto/DittoMapper.java index f8e20cdc47..bcc7c25a91 100644 --- a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/ditto/DittoMapper.java +++ b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/ditto/DittoMapper.java @@ -35,6 +35,7 @@ import org.eclipse.vorto.service.mapping.DataInput; import org.eclipse.vorto.service.mapping.IDataMapper; import org.eclipse.vorto.service.mapping.IMappingSpecification; +import org.eclipse.vorto.service.mapping.MappingContext; /** * @@ -67,7 +68,7 @@ public DittoMapper(IMappingSpecification loader,ClassFunctions customFunctions) } } - public DittoOutput map(DataInput input) { + public DittoOutput map(DataInput input, MappingContext mappingContext) { JXPathContext context = newContext(input.getValue()); context.setFunctions(converterLibrary); @@ -77,7 +78,9 @@ public DittoOutput map(DataInput input) { final Infomodel deviceInfoModel = specification.getInfoModel(); for (ModelProperty fbProperty : deviceInfoModel.getFunctionblocks()) { - output.withFeature(mapFunctionBlock(fbProperty, context)); + if (mappingContext.isIncluded(fbProperty.getName())) { + output.withFeature(mapFunctionBlock(fbProperty, context)); + } } return output; @@ -96,7 +99,6 @@ private Feature mapFunctionBlock(ModelProperty fbProperty, JXPathContext context featureBuilder.withStatusProperty(statusProperty.getName(), toType(value,statusProperty.getType())); } else if (sourceStereotype.get().getAttributes().containsKey(ATTRIBUTE_XPATH)) { String expression = replacePlaceHolders(sourceStereotype.get().getAttributes().get(ATTRIBUTE_XPATH),sourceStereotype.get().getAttributes()); - featureBuilder.withStatusProperty(statusProperty.getName(), context.getValue(expression)); } } @@ -139,15 +141,11 @@ private Object toType(String value, IReferenceType type) { throw new UnsupportedOperationException(); } } - - private JXPathContext getSharedContext() { - JXPathContext context = JXPathContext.newContext(null); - context.setLenient(true); - return context; - } private JXPathContext newContext(Object ctxObject) { - return JXPathContext.newContext(getSharedContext(),ctxObject); + JXPathContext context = JXPathContext.newContext(ctxObject); + context.setLenient(true); + return context; } } diff --git a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/MappingSpecificationProblem.java b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/MappingSpecificationProblem.java new file mode 100644 index 0000000000..7d6558f859 --- /dev/null +++ b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/MappingSpecificationProblem.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2015-2016 Bosch Software Innovations GmbH and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * The Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Bosch Software Innovations GmbH - Please refer to git log + */ +package org.eclipse.vorto.service.mapping.spec; + +public class MappingSpecificationProblem extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public MappingSpecificationProblem(String msg, Throwable t) { + super(msg, t); + } + + public MappingSpecificationProblem(String msg) { + super(msg); + } +} diff --git a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/RemoteMappingSpecification.java b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/RemoteMappingSpecification.java index ffca74f4e8..df7a424eb7 100644 --- a/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/RemoteMappingSpecification.java +++ b/server/repo/repository-mapping/src/main/java/org/eclipse/vorto/service/mapping/spec/RemoteMappingSpecification.java @@ -46,8 +46,12 @@ public class RemoteMappingSpecification implements IMappingSpecification { private FunctionLibrary library = new FunctionLibrary(); - public RemoteMappingSpecification(ModelId infoModelId, String mappingKey, String endpoint) { + public RemoteMappingSpecification(ModelId infoModelId, String mappingKey, String endpoint, Optional proxyHost, Optional proxyPort) { RepositoryClientBuilder builder = RepositoryClientBuilder.newBuilder().setBaseUrl(endpoint); + if (proxyHost.isPresent() && proxyPort.isPresent()) { + builder.setProxyHost(proxyHost.get()); + builder.setProxyPort(proxyPort.get()); + } this.repositoryClient = builder.buildModelRepositoryClient(); this.modelId = infoModelId; this.mappingKey = mappingKey; @@ -58,6 +62,10 @@ public RemoteMappingSpecification(ModelId infoModelId, String mappingKey, String private void fetchModels() { try { this.infomodel = this.repositoryClient.getContent(this.modelId, Infomodel.class, this.mappingKey).get(); + if (this.infomodel == null) { + throw new IllegalArgumentException("Information Model cannot be found with given model ID and/or key"); + } + for (ModelProperty fbProperty : this.infomodel.getFunctionblocks()) { ModelId fbModelId = (ModelId)fbProperty.getType(); FunctionblockModel fbm = this.repositoryClient.getContent(fbModelId, FunctionblockModel.class,this.mappingKey).get(); @@ -75,7 +83,7 @@ private void fetchModels() { this.fbs.put(fbModelId, fbm); } } catch (Exception e) { - throw new RuntimeException(e); + throw new MappingSpecificationProblem("Cannot create mapping specification", e); } diff --git a/server/repo/repository-mapping/src/test/java/org/eclipse/vorto/service/mapping/JsonMappingTest.java b/server/repo/repository-mapping/src/test/java/org/eclipse/vorto/service/mapping/JsonMappingTest.java index 785fca653e..1f15f9c1f7 100644 --- a/server/repo/repository-mapping/src/test/java/org/eclipse/vorto/service/mapping/JsonMappingTest.java +++ b/server/repo/repository-mapping/src/test/java/org/eclipse/vorto/service/mapping/JsonMappingTest.java @@ -1,6 +1,7 @@ package org.eclipse.vorto.service.mapping; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.util.Arrays; import java.util.HashMap; @@ -16,9 +17,10 @@ import org.eclipse.vorto.repository.api.content.PrimitiveType; import org.eclipse.vorto.repository.api.content.Stereotype; import org.eclipse.vorto.service.mapping.converters.JavascriptFunctions; +import org.eclipse.vorto.service.mapping.ditto.DittoMapper; import org.eclipse.vorto.service.mapping.ditto.DittoOutput; import org.eclipse.vorto.service.mapping.ditto.Feature; -import org.eclipse.vorto.service.mapping.ditto.DittoMapper; +import org.eclipse.vorto.service.mapping.spec.MappingSpecificationProblem; import org.junit.Test; public class JsonMappingTest { @@ -31,7 +33,7 @@ public void testDittoMapping() throws Exception { String json = "{\"clickType\" : \"DOUBLE\", \"batteryVoltage\": \"2322mV\"}"; - DittoOutput mappedDittoOutput = mapper.map(DataInput.newInstance().fromJson(json)); + DittoOutput mappedDittoOutput = mapper.map(DataInput.newInstance().fromJson(json),MappingContext.empty()); Feature buttonFeature = mappedDittoOutput.getFeatures().get("button"); @@ -47,17 +49,43 @@ public void testDittoMapping() throws Exception { } + @Test + public void testDittoMappingOnlyOneFeature() throws Exception { + + DittoMapper mapper = IDataMapper.newBuilder() + .withSpecification(new TestMappingSpecification()).buildDittoMapper(); + + String json = "{\"clickType\" : \"DOUBLE\"}"; + + DittoOutput mappedDittoOutput = mapper.map(DataInput.newInstance().fromJson(json),MappingContext.functionblockProperties("button")); + + Feature buttonFeature = mappedDittoOutput.getFeatures().get("button"); + + assertEquals(true,(Boolean)buttonFeature.getProperty("digital_input_state")); + assertEquals(2,buttonFeature.getProperty("digital_input_count")); + + assertNull(mappedDittoOutput.getFeatures().get("voltage")); + + System.out.println(mappedDittoOutput.toJson()); + + } + + @Test(expected = MappingSpecificationProblem.class) + public void testBuildMappingSpecificationForInvalidModelId() { + IMappingSpecification.newBuilder().modelId("devices.PhilipsLivingBloo:1.0.0").build(); + } + @Test public void testDittoMappingFromRemoteRepository() throws Exception { DittoMapper mapper = IDataMapper.newBuilder() - .withSpecification(IMappingSpecification.newBuilder().modelId("devices.aws.button.AWSIoTButton:1.0.0").key("awsiotbutton").build()).buildDittoMapper(); + .withSpecification(IMappingSpecification.newBuilder().modelId("devices.aws.button.AWSIoTButton:1.0.0").build()).buildDittoMapper(); Map input = new HashMap(); input.put("clickType", "DOUBLE"); input.put("batteryVoltage", "2322mV"); - DittoOutput mappedDittoOutput = mapper.map(DataInput.newInstance().fromObject(input)); + DittoOutput mappedDittoOutput = mapper.map(DataInput.newInstance().fromObject(input),MappingContext.empty()); Feature buttonFeature = mappedDittoOutput.getFeatures().get("button"); @@ -73,7 +101,7 @@ public void testDittoMappingFromRemoteRepository() throws Exception { System.out.println(mappedDittoOutput.toJson()); } - + private static class TestMappingSpecification implements IMappingSpecification { private static Map FBS = new HashMap(2);