Skip to content

Commit

Permalink
Fixes #752
Browse files Browse the repository at this point in the history
  • Loading branch information
aedelmann committed Sep 12, 2017
1 parent bc03d12 commit 865224c
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

public interface IDataMapper<Output extends JsonPayload> {

Output map(DataInput input);
Output map(DataInput input, MappingContext context);

static DataMapperBuilder newBuilder() {
return new DataMapperBuilder();
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String> 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<String> 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
*
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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));
}
}
Expand Down Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> proxyHost, Optional<Integer> 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;
Expand All @@ -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();
Expand All @@ -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);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 {
Expand All @@ -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");

Expand All @@ -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<String, Object> input = new HashMap<String, Object>();
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");
Expand All @@ -73,7 +101,7 @@ public void testDittoMappingFromRemoteRepository() throws Exception {
System.out.println(mappedDittoOutput.toJson());

}

private static class TestMappingSpecification implements IMappingSpecification {

private static Map<ModelId, FunctionblockModel> FBS = new HashMap<ModelId, FunctionblockModel>(2);
Expand Down

0 comments on commit 865224c

Please sign in to comment.