package org.molgenis.data.mapper.algorithmgenerator.generator;
import com.google.common.collect.Lists;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.molgenis.data.DataService;
import org.molgenis.data.Entity;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.AttributeFactory;
import org.molgenis.data.meta.model.EntityType;
import org.molgenis.data.meta.model.EntityTypeFactory;
import org.molgenis.data.support.DynamicEntity;
import org.molgenis.test.data.AbstractMolgenisSpringTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.stream.Stream;
import static com.google.common.collect.ImmutableMap.of;
import static org.molgenis.data.meta.AttributeType.CATEGORICAL;
import static org.molgenis.data.meta.AttributeType.INT;
import static org.molgenis.data.meta.model.EntityType.AttributeRole.ROLE_ID;
import static org.molgenis.data.meta.model.EntityType.AttributeRole.ROLE_LABEL;
public class OneToManyCategoryAlgorithmGeneratorTest extends AbstractMolgenisSpringTest
{
@Autowired
private EntityTypeFactory entityTypeFactory;
@Autowired
private AttributeFactory attrMetaFactory;
private OneToManyCategoryAlgorithmGenerator categoryAlgorithmGenerator;
private Attribute targetAttribute;
private Attribute sourceAttribute;
private Attribute sourceAttribute1;
private Attribute sourceAttribute2;
private EntityType targetEntityType;
private EntityType sourceEntityType;
@BeforeMethod
public void init()
{
DataService dataService = Mockito.mock(DataService.class);
categoryAlgorithmGenerator = new OneToManyCategoryAlgorithmGenerator(dataService);
EntityType targetRefEntityType = entityTypeFactory.create("POTATO_REF");
Attribute targetCodeAttribute = attrMetaFactory.create().setName("code").setDataType(INT);
Attribute targetLabelAttribute = attrMetaFactory.create().setName("label");
targetRefEntityType.addAttribute(targetCodeAttribute, ROLE_ID);
targetRefEntityType.addAttribute(targetLabelAttribute, ROLE_LABEL);
targetAttribute = attrMetaFactory.create().setName("Current Consumption Frequency of Potatoes")
.setDataType(CATEGORICAL);
targetAttribute.setRefEntity(targetRefEntityType);
Entity targetEntity1 = new DynamicEntity(targetRefEntityType, of("code", 1, "label", "Almost daily + daily"));
Entity targetEntity2 = new DynamicEntity(targetRefEntityType, of("code", 2, "label", "Several times a week"));
Entity targetEntity3 = new DynamicEntity(targetRefEntityType, of("code", 3, "label", "About once a week"));
Entity targetEntity4 = new DynamicEntity(targetRefEntityType,
of("code", 4, "label", "Never + fewer than once a week"));
Entity targetEntity5 = new DynamicEntity(targetRefEntityType, of("code", 9, "label", "missing"));
Mockito.when(dataService.findAll(targetRefEntityType.getName())).thenAnswer(new Answer<Stream<Entity>>()
{
@Override
public Stream<Entity> answer(InvocationOnMock invocation) throws Throwable
{
return Stream.of(targetEntity1, targetEntity2, targetEntity3, targetEntity4, targetEntity5);
}
});
targetEntityType = entityTypeFactory.create("target");
targetEntityType.addAttribute(targetAttribute);
EntityType sourceRefEntityType = createEntityType("LifeLines_POTATO_REF");
sourceAttribute = attrMetaFactory.create().setName("MESHED_POTATO").setDataType(CATEGORICAL);
sourceAttribute.setLabel(
"How often did you eat boiled or mashed potatoes (also in stew) in the past month? Baked potatoes are asked later");
sourceAttribute.setRefEntity(sourceRefEntityType);
Entity sourceEntity1 = new DynamicEntity(targetRefEntityType, of("code", 1, "label", "Not this month"));
Entity sourceEntity2 = new DynamicEntity(targetRefEntityType, of("code", 2, "label", "1 day per month"));
Entity sourceEntity3 = new DynamicEntity(targetRefEntityType, of("code", 3, "label", "2-3 days per month"));
Entity sourceEntity4 = new DynamicEntity(targetRefEntityType, of("code", 4, "label", "1 day per week"));
Entity sourceEntity5 = new DynamicEntity(targetRefEntityType, of("code", 5, "label", "2-3 days per week"));
Entity sourceEntity6 = new DynamicEntity(targetRefEntityType, of("code", 6, "label", "4-5 days per week"));
Entity sourceEntity7 = new DynamicEntity(targetRefEntityType, of("code", 7, "label", "6-7 days per week"));
Mockito.when(dataService.findAll(sourceRefEntityType.getName())).thenAnswer(new Answer<Stream<Entity>>()
{
@Override
public Stream<Entity> answer(InvocationOnMock invocation) throws Throwable
{
return Stream
.of(sourceEntity1, sourceEntity2, sourceEntity3, sourceEntity4, sourceEntity5, sourceEntity6,
sourceEntity7);
}
});
EntityType sourceRefEntityType1 = createEntityType("Mitchelstown_POTATO_REF");
sourceAttribute1 = attrMetaFactory.create().setName("MESHED_POTATO_1").setDataType(CATEGORICAL);
sourceAttribute1.setLabel(
"How often did you eat boiled or mashed potatoes (also in stew) in the past month? Baked potatoes are asked later");
sourceAttribute1.setRefEntity(sourceRefEntityType1);
Entity sourceEntity8 = new DynamicEntity(targetRefEntityType,
of("code", 1, "label", "never/less than 1 per month"));
Entity sourceEntity9 = new DynamicEntity(targetRefEntityType, of("code", 2, "label", "1-3 per month"));
Entity sourceEntity10 = new DynamicEntity(targetRefEntityType, of("code", 3, "label", "once a week"));
Entity sourceEntity11 = new DynamicEntity(targetRefEntityType, of("code", 4, "label", "2-4 per week"));
Entity sourceEntity12 = new DynamicEntity(targetRefEntityType, of("code", 5, "label", "5-6 per week"));
Entity sourceEntity13 = new DynamicEntity(targetRefEntityType, of("code", 6, "label", "once a day"));
Entity sourceEntity14 = new DynamicEntity(targetRefEntityType, of("code", 7, "label", "2-3 per day"));
Entity sourceEntity15 = new DynamicEntity(targetRefEntityType, of("code", 8, "label", "4-5 per day"));
Entity sourceEntity16 = new DynamicEntity(targetRefEntityType, of("code", 9, "label", "6+ per day"));
Mockito.when(dataService.findAll(sourceRefEntityType1.getName())).thenAnswer(new Answer<Stream<Entity>>()
{
@Override
public Stream<Entity> answer(InvocationOnMock invocation) throws Throwable
{
return Stream.of(sourceEntity8, sourceEntity9, sourceEntity10, sourceEntity11, sourceEntity12,
sourceEntity13, sourceEntity14, sourceEntity15, sourceEntity16);
}
});
EntityType sourceRefEntityType2 = createEntityType("Mitchelstown_Stroke_REF");
sourceAttribute2 = attrMetaFactory.create().setName("Stroke").setDataType(CATEGORICAL);
sourceAttribute2.setLabel("History of stroke");
sourceAttribute2.setRefEntity(sourceRefEntityType2);
Entity sourceEntity17 = new DynamicEntity(targetRefEntityType, of("code", 1, "label", "yes"));
Entity sourceEntity18 = new DynamicEntity(targetRefEntityType, of("code", 2, "label", "no"));
Entity sourceEntity19 = new DynamicEntity(targetRefEntityType, of("code", 9, "label", "missing"));
Mockito.when(dataService.findAll(sourceRefEntityType2.getName())).thenAnswer(new Answer<Stream<Entity>>()
{
@Override
public Stream<Entity> answer(InvocationOnMock invocation) throws Throwable
{
return Stream.of(sourceEntity17, sourceEntity18, sourceEntity19);
}
});
sourceEntityType = entityTypeFactory.create("source");
sourceEntityType.addAttributes(Lists.newArrayList(sourceAttribute, sourceAttribute1, sourceAttribute2));
}
private EntityType createEntityType(String entityName)
{
EntityType sourceRefEntityType = entityTypeFactory.create(entityName);
Attribute sourceCodeAttribute = attrMetaFactory.create().setName("code").setDataType(INT);
Attribute sourceLabelAttribute = attrMetaFactory.create().setName("label");
sourceRefEntityType.addAttribute(sourceCodeAttribute, ROLE_ID);
sourceRefEntityType.addAttribute(sourceLabelAttribute, ROLE_LABEL);
return sourceRefEntityType;
}
@Test
public void testIsSuitable()
{
Assert.assertTrue(categoryAlgorithmGenerator
.isSuitable(targetAttribute, Arrays.asList(sourceAttribute, sourceAttribute1)));
}
@Test
public void testGenerate()
{
String expected = "var SUM_WEIGHT;\nif($('MESHED_POTATO').isNull().value() && $('MESHED_POTATO_1').isNull().value()){\n\tSUM_WEIGHT = new newValue();\n\tSUM_WEIGHT.value();\n}else{\n\tSUM_WEIGHT = new newValue(0);\n\tSUM_WEIGHT.plus($('MESHED_POTATO').map({\"1\":0,\"2\":0.2,\"3\":0.6,\"4\":1,\"5\":2.5,\"6\":4.5,\"7\":6.5}, null, null).value());\n\tSUM_WEIGHT.plus($('MESHED_POTATO_1').map({\"1\":0.1,\"2\":0.5,\"3\":1,\"4\":3,\"5\":5.5,\"6\":7,\"7\":17.5,\"8\":31.5,\"9\":42}, null, null).value());\n\tSUM_WEIGHT.group([0,1,3,6,7]).map({\"-0\":\"4\",\"0-1\":\"4\",\"1-3\":\"3\",\"3-6\":\"2\",\"6-7\":\"1\",\"7+\":\"1\"}, null, null).value();\n}";
String generateMultipleAttributes = categoryAlgorithmGenerator
.generate(targetAttribute, Arrays.asList(sourceAttribute, sourceAttribute1), targetEntityType,
sourceEntityType);
Assert.assertEquals(generateMultipleAttributes, expected);
}
@Test
public void testGenerateWeightedMap()
{
String expected = "$('MESHED_POTATO').map({\"1\":0,\"2\":0.2,\"3\":0.6,\"4\":1,\"5\":2.5,\"6\":4.5,\"7\":6.5}, null, null).value()";
String actual = categoryAlgorithmGenerator.generateWeightedMap(sourceAttribute);
Assert.assertEquals(actual, expected);
}
@Test
public void testGenerateWeightedMapForTarget()
{
Assert.assertEquals(categoryAlgorithmGenerator.groupCategoryValues(targetAttribute),
".group([0,1,3,6,7]).map({\"-0\":\"4\",\"0-1\":\"4\",\"1-3\":\"3\",\"3-6\":\"2\",\"6-7\":\"1\",\"7+\":\"1\"}, null, null).value();");
}
@Test
public void testGenerateWeightedMapForSource()
{
Assert.assertEquals(categoryAlgorithmGenerator.groupCategoryValues(sourceAttribute),
".group([0,1,2,3,4,5,6,7]).map({\"-0\":\"1\",\"0-1\":\"4\",\"1-2\":\"4\",\"2-3\":\"5\",\"4-5\":\"6\",\"6-7\":\"7\",\"7+\":\"7\"}, null, null).value();");
}
@Test
public void testSuitableForGeneratingWeightedMap()
{
Assert.assertTrue(categoryAlgorithmGenerator
.suitableForGeneratingWeightedMap(targetAttribute, Arrays.asList(sourceAttribute, sourceAttribute1)));
Assert.assertFalse(categoryAlgorithmGenerator.suitableForGeneratingWeightedMap(targetAttribute,
Arrays.asList(sourceAttribute, sourceAttribute1, sourceAttribute2)));
}
@Test
public void testHomogenousGenerator()
{
String expectedAlgorithm = "var SUM_WEIGHT;\nif($('MESHED_POTATO').isNull().value() && $('MESHED_POTATO_1').isNull().value()){\n\tSUM_WEIGHT = new newValue();\n\tSUM_WEIGHT.value();\n}else{\n\tSUM_WEIGHT = new newValue(0);\n\tSUM_WEIGHT.plus($('MESHED_POTATO').map({\"1\":0,\"2\":0.2,\"3\":0.6,\"4\":1,\"5\":2.5,\"6\":4.5,\"7\":6.5}, null, null).value());\n\tSUM_WEIGHT.plus($('MESHED_POTATO_1').map({\"1\":0.1,\"2\":0.5,\"3\":1,\"4\":3,\"5\":5.5,\"6\":7,\"7\":17.5,\"8\":31.5,\"9\":42}, null, null).value());\n\tSUM_WEIGHT.group([0,1,3,6,7]).map({\"-0\":\"4\",\"0-1\":\"4\",\"1-3\":\"3\",\"3-6\":\"2\",\"6-7\":\"1\",\"7+\":\"1\"}, null, null).value();\n}";
Assert.assertEquals(categoryAlgorithmGenerator
.generate(targetAttribute, Arrays.asList(sourceAttribute, sourceAttribute1), targetEntityType,
sourceEntityType), expectedAlgorithm);
}
@Test
public void testHeterogenousGenerator()
{
String expectedAlgorithm = "$('MESHED_POTATO_1').map({\"1\":\"4\",\"2\":\"4\",\"3\":\"3\",\"4\":\"2\",\"5\":\"2\",\"6\":\"1\",\"7\":\"1\",\"8\":\"1\",\"9\":\"1\"}, null, null).value();$('MESHED_POTATO').map({\"1\":\"4\",\"2\":\"4\",\"3\":\"4\",\"4\":\"3\",\"5\":\"2\",\"6\":\"2\",\"7\":\"1\"}, null, null).value();$('Stroke').map({\"1\":\"2\",\"2\":\"4\",\"9\":\"9\"}, null, null).value();";
String actual = categoryAlgorithmGenerator
.generate(targetAttribute, Arrays.asList(sourceAttribute1, sourceAttribute, sourceAttribute2),
targetEntityType, sourceEntityType);
Assert.assertEquals(actual, expectedAlgorithm);
}
@Test
public void testCreateAlgorithmNullCheck()
{
String actual = "var SUM_WEIGHT;\nif($('MESHED_POTATO_1').isNull().value() && $('MESHED_POTATO').isNull().value() && $('Stroke').isNull().value()){\n\tSUM_WEIGHT = new newValue();\n\tSUM_WEIGHT.value();\n}";
String createAlgorithmNullCheck = categoryAlgorithmGenerator.createAlgorithmNullCheckIfStatement(
Arrays.asList(sourceAttribute1, sourceAttribute, sourceAttribute2));
Assert.assertEquals(createAlgorithmNullCheck, actual);
}
@Test
void testCreateAlgorithmElseBlock()
{
String actual = "else{\n\tSUM_WEIGHT = new newValue(0);\n\tSUM_WEIGHT.plus($('MESHED_POTATO_1').map({\"1\":0.1,\"2\":0.5,\"3\":1,\"4\":3,\"5\":5.5,\"6\":7,\"7\":17.5,\"8\":31.5,\"9\":42}, null, null).value());\n\tSUM_WEIGHT.plus($('MESHED_POTATO').map({\"1\":0,\"2\":0.2,\"3\":0.6,\"4\":1,\"5\":2.5,\"6\":4.5,\"7\":6.5}, null, null).value());\n\tSUM_WEIGHT.group([0,1,3,6,7]).map({\"-0\":\"4\",\"0-1\":\"4\",\"1-3\":\"3\",\"3-6\":\"2\",\"6-7\":\"1\",\"7+\":\"1\"}, null, null).value();\n}";
String createAlgorithmElseBlock = categoryAlgorithmGenerator.createAlgorithmElseBlock(targetAttribute,
Arrays.asList(sourceAttribute1, sourceAttribute, sourceAttribute2));
Assert.assertEquals(createAlgorithmElseBlock, actual);
}
}