package nl.ipo.cds.dao.attributemapping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import nl.ipo.cds.attributemapping.MapperContext;
import nl.ipo.cds.attributemapping.executer.OperationExecuter;
import nl.ipo.cds.attributemapping.operations.OperationInputType;
import nl.ipo.cds.attributemapping.operations.OperationType;
import nl.ipo.cds.attributemapping.operations.OutputOperationType;
import nl.ipo.cds.categories.IntegrationTests;
import nl.ipo.cds.dao.BaseManagerDaoTest;
import nl.ipo.cds.domain.AttributeMapping;
import nl.ipo.cds.domain.AttributeType;
import nl.ipo.cds.domain.Dataset;
import nl.ipo.cds.domain.FeatureTypeAttribute;
import nl.ipo.cds.domain.MappingOperation.MappingOperationType;
import nl.ipo.cds.domain.QName;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback = true, transactionManager = "transactionManager")
@Category(IntegrationTests.class)
public class AttributeMappingDaoTest extends BaseManagerDaoTest {
private AttributeMappingDao dao;
@PersistenceContext
private EntityManager entityManager;
private Set<FeatureTypeAttribute> inputAttributes;
private Set<OperationType> operationTypes;
@Before
public void createAttributeMappingDao () throws Exception {
buildDB ();
inputAttributes = new HashSet<FeatureTypeAttribute> ();
inputAttributes.add (createFeatureTypeAttribute ("a", AttributeType.STRING));
inputAttributes.add (createFeatureTypeAttribute ("b", AttributeType.BOOLEAN));
operationTypes = new HashSet<OperationType> ();
operationTypes.add (createOperationType ());
dao = new AttributeMappingDao (managerDao, inputAttributes, operationTypes);
assertNotNull (dao);
}
@Test
public void testPutAttributeMapping () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null);
// Write the attribute mapping:
dao.putAttributeMapping (dataset, createOutputOperationType ("testAttribute"), operation, false);
// Read the resulting mapping:
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertNotNull (mapping);
assertEquals ("testAttribute", mapping.getAttributeName ());
assertNotNull (mapping.getRootOperation ());
assertNull (mapping.getRootOperation ().getInputAttributeType());
assertEquals (0, mapping.getRootOperation ().getInputs ().size ());
assertEquals ("testTransformOperation", mapping.getRootOperation ().getOperationName ());
assertNull (mapping.getRootOperation ().getParent ());
assertNull (mapping.getRootOperation ().getProperties ());
}
@Test
public void testPutAttributeMappingProperties () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (new PropertyClass ("a", 42, true));
dao.putAttributeMapping (dataset, createOutputOperationType ("testAttribute"), operation, false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertNotNull (mapping.getRootOperation ().getProperties ());
assertTrue (mapping.getRootOperation ().getProperties ().length () > 0);
assertTrue (mapping.getRootOperation ().getProperties ().startsWith ("{"));
assertTrue (mapping.getRootOperation ().getProperties ().endsWith ("}"));
}
@Test
public void testPutAttributeMappingInputs () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, createTransformOperation (null), createTransformOperation (null));
dao.putAttributeMapping (dataset, createOutputOperationType ("testAttribute"), operation, false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertEquals (2, mapping.getRootOperation ().getInputs ().size ());
assertEquals ("testTransformOperation", mapping.getRootOperation ().getInputs ().get (0).getOperationName ());
assertEquals ("testTransformOperation", mapping.getRootOperation ().getInputs ().get (1).getOperationName ());
assertSame (mapping.getRootOperation (), mapping.getRootOperation ().getInputs ().get (0).getParent ());
assertSame (mapping.getRootOperation (), mapping.getRootOperation ().getInputs ().get (1).getParent ());
}
@Test
public void testPutAttributeMappingInputAttributes () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, createInputOperation ("a", AttributeType.STRING), createInputOperation ("b", AttributeType.BOOLEAN));
dao.putAttributeMapping (dataset, createOutputOperationType ("testAttribute"), operation, false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertEquals (2, mapping.getRootOperation ().getInputs ().size ());
assertEquals (MappingOperationType.INPUT_OPERATION, mapping.getRootOperation ().getInputs ().get (0).getOperationType ());
assertEquals ("a", mapping.getRootOperation ().getInputs ().get (0).getOperationName ());
assertEquals (0, mapping.getRootOperation ().getInputs ().get (0).getInputs().size ());
assertEquals (AttributeType.STRING, mapping.getRootOperation ().getInputs ().get (0).getInputAttributeType ());
assertNull (mapping.getRootOperation ().getInputs ().get (0).getProperties ());
assertEquals (MappingOperationType.INPUT_OPERATION, mapping.getRootOperation ().getInputs ().get (1).getOperationType ());
assertEquals ("b", mapping.getRootOperation ().getInputs ().get (1).getOperationName ());
assertEquals (0, mapping.getRootOperation ().getInputs ().get (1).getInputs().size ());
assertEquals (AttributeType.BOOLEAN, mapping.getRootOperation ().getInputs ().get (1).getInputAttributeType ());
assertNull (mapping.getRootOperation ().getInputs ().get (1).getProperties ());
}
@Test
public void testPutAttributeMappingNullInputs () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, null, createInputOperation ("a", AttributeType.STRING), null, createInputOperation ("b", AttributeType.BOOLEAN), null);
dao.putAttributeMapping (dataset, createOutputOperationType ("testAttribute"), operation, false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertEquals (4, mapping.getRootOperation ().getInputs ().size ());
assertNull (mapping.getRootOperation ().getInputs ().get (0));
assertNotNull (mapping.getRootOperation ().getInputs ().get (1));
assertNull (mapping.getRootOperation ().getInputs ().get (2));
assertNotNull (mapping.getRootOperation ().getInputs ().get (3));
}
@Test
public void testUpdateAttributeMapping () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
// Write the attribute mapping:
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO operation2 = createTransformOperation (null);
dao.putAttributeMapping (dataset, operationType, operation2, false);
// Read the resulting mapping:
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertNotNull (mapping);
assertEquals ("testAttribute", mapping.getAttributeName ());
assertNotNull (mapping.getRootOperation ());
assertNull (mapping.getRootOperation ().getInputAttributeType());
assertEquals (0, mapping.getRootOperation ().getInputs ().size ());
assertEquals ("testTransformOperation", mapping.getRootOperation ().getOperationName ());
assertNull (mapping.getRootOperation ().getParent ());
assertNull (mapping.getRootOperation ().getProperties ());
}
@Test
public void testUpdateAttributeMappingInputType () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, createTransformOperation (null), createTransformOperation (null));
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO operation2 = createTransformOperation (null, createInputOperation ("a", AttributeType.STRING), createTransformOperation (null));
dao.putAttributeMapping (dataset, operationType, operation2, false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertEquals (2, mapping.getRootOperation ().getInputs ().size ());
assertEquals (MappingOperationType.INPUT_OPERATION, mapping.getRootOperation ().getInputs ().get (0).getOperationType ());
assertEquals ("a", mapping.getRootOperation ().getInputs ().get (0).getOperationName ());
assertEquals (0, mapping.getRootOperation ().getInputs ().get (0).getInputs().size ());
assertEquals (AttributeType.STRING, mapping.getRootOperation ().getInputs ().get (0).getInputAttributeType ());
assertNull (mapping.getRootOperation ().getInputs ().get (0).getProperties ());
assertEquals ("testTransformOperation", mapping.getRootOperation ().getInputs ().get (1).getOperationName ());
assertSame (mapping.getRootOperation (), mapping.getRootOperation ().getInputs ().get (1).getParent ());
}
@Test
public void testUpdateAttributeMappingInputCount () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, createTransformOperation (null), createTransformOperation (null)), false);
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, createTransformOperation (null), createTransformOperation (null), createTransformOperation (null)), false);
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, createTransformOperation (null)), false);
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null), false);
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, createTransformOperation (null)), false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertEquals (1, mapping.getRootOperation ().getInputs ().size ());
assertEquals ("testTransformOperation", mapping.getRootOperation ().getInputs ().get (0).getOperationName ());
assertSame (mapping.getRootOperation (), mapping.getRootOperation ().getInputs ().get (0).getParent ());
}
@Test
public void testUpdateAttributeMappingProperties () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, createTransformOperation (new PropertyClass ("a", 42, true)), false);
dao.putAttributeMapping (dataset, operationType, createTransformOperation (new PropertyClass ("b", 43, false)), false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertNotNull (mapping.getRootOperation ().getProperties ());
assertTrue (mapping.getRootOperation ().getProperties ().length () > 0);
assertTrue (mapping.getRootOperation ().getProperties ().startsWith ("{"));
assertTrue (mapping.getRootOperation ().getProperties ().endsWith ("}"));
final OperationDTO op = dao.getAttributeMapping (dataset, operationType);
assertTrue (op instanceof TransformOperationDTO);
assertTrue (((TransformOperationDTO)op).getOperationProperties () instanceof PropertyClass);
assertEquals (new PropertyClass ("b", 43, false), ((PropertyClass)((TransformOperationDTO)op).getOperationProperties ()));
}
@Test
public void testUpdateAttributeMappingNullInputs () throws Exception {
// Turn previously existing inputs into null values:
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, createTransformOperation (null), createTransformOperation (null), createTransformOperation (null), createTransformOperation (null)), false);
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, null, null, null, createTransformOperation (null)), false);
final AttributeMapping mapping = managerDao.getAttributeMapping (dataset, "testAttribute");
assertEquals (4, mapping.getRootOperation ().getInputs ().size ());
assertNull (mapping.getRootOperation ().getInputs ().get (0));
assertNull (mapping.getRootOperation ().getInputs ().get (1));
assertNull (mapping.getRootOperation ().getInputs ().get (2));
assertNotNull (mapping.getRootOperation ().getInputs ().get (3));
}
/**
* Tests a 'cascading' delete on an attribute mapping: a complex tree of mapping operations is
* removed in a single call. Mapping operations should be removed in the correct order.
*
* @throws Exception
*/
@Test
public void testUpdateAttributeMappingCascade () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null, createTransformOperation (null, createTransformOperation (null, createTransformOperation (null)), createTransformOperation (null, createTransformOperation (null)))), false);
entityManager.flush ();
dao.putAttributeMapping (dataset, operationType, createTransformOperation (null), false);
entityManager.flush ();
}
@Test
public void testGetAttributeMapping () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO op = dao.getAttributeMapping (dataset, operationType);
assertNotNull (op);
assertEquals (operation.getOperationType (), op.getOperationType ());
assertEquals (operation.getInputs ().size (), op.getInputs ().size ());
assertEquals (operation.getOperationType (), op.getOperationType ());
assertEquals (operation.getOperationProperties (), op.getOperationProperties ());
}
@Test
public void testGetAttributeMappingProperties () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (new PropertyClass ("a", 42, true));
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO op = dao.getAttributeMapping (dataset, operationType);
assertNotNull (op.getOperationProperties ());
assertEquals (operation.getOperationProperties (), op.getOperationProperties ());
}
@Test
public void testGetAttributeMappingInputs () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, createTransformOperation (null), createTransformOperation (null));
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO op = dao.getAttributeMapping (dataset, operationType);
assertEquals (2, op.getInputs ().size ());
assertEquals (operation.getInputs ().get (0).getOperation ().getOperationType (), op.getInputs ().get (0).getOperation ().getOperationType ());
assertEquals (operation.getInputs ().get (0).getOperation ().getOperationProperties (), op.getInputs ().get (0).getOperation ().getOperationProperties ());
}
@Test
public void testGetAttributeMappingInputAttributes () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, createInputOperation ("a", AttributeType.STRING), createInputOperation ("b", AttributeType.BOOLEAN));
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO op = dao.getAttributeMapping (dataset, operationType);
assertEquals (2, op.getInputs ().size ());
assertTrue (op.getInputs ().get (0).getOperation () instanceof InputOperationDTO);
assertEquals ("a", ((InputOperationDTO)op.getInputs ().get (0).getOperation ()).getAttributeName ());
assertEquals (AttributeType.STRING, ((InputOperationDTO)op.getInputs ().get (0).getOperation ()).getAttributeType ());
assertNotNull (((InputOperationDTO)op.getInputs ().get (0).getOperation ()).getAttribute ());
assertTrue (op.getInputs ().get (1).getOperation () instanceof InputOperationDTO);
assertEquals ("b", ((InputOperationDTO)op.getInputs ().get (1).getOperation ()).getAttributeName ());
assertEquals (AttributeType.BOOLEAN, ((InputOperationDTO)op.getInputs ().get (1).getOperation ()).getAttributeType ());
assertNotNull (((InputOperationDTO)op.getInputs ().get (1).getOperation ()).getAttribute ());
}
@Test
public void testGetAttributeMappingNullInputs () throws Exception {
final Dataset dataset = managerDao.getAllDatasets ().get (0);
final OperationDTO operation = createTransformOperation (null, null, createInputOperation ("a", AttributeType.STRING), null, createInputOperation ("b", AttributeType.BOOLEAN), null);
final OutputOperationType operationType = createOutputOperationType ("testAttribute");
dao.putAttributeMapping (dataset, operationType, operation, false);
final OperationDTO op = dao.getAttributeMapping (dataset, operationType);
assertEquals (4, op.getInputs ().size ());
assertNull (op.getInputs ().get (0).getOperation ());
assertNotNull (op.getInputs ().get (1).getOperation ());
assertNull (op.getInputs ().get (2).getOperation ());
assertNotNull (op.getInputs ().get (3).getOperation ());
}
public static class PropertyClass {
private String a;
private int b;
private boolean c;
public PropertyClass () {
}
public PropertyClass (final String a, final int b, final boolean c) {
this.a = a;
this.b = b;
this.c = c;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public boolean isC() {
return c;
}
public void setC(boolean c) {
this.c = c;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + b;
result = prime * result + (c ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PropertyClass other = (PropertyClass) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (b != other.b)
return false;
if (c != other.c)
return false;
return true;
}
}
private static OutputOperationType createOutputOperationType (final String name) {
return new OutputOperationType() {
@Override
public Type getReturnType() {
return Object.class;
}
@Override
public Class<?> getPropertyBeanClass() {
return null;
}
@Override
public String getName() {
return name;
}
@Override
public String getLabel(Locale locale) {
return getName ();
}
@Override
public String getFormatLabel (final Locale locale) {
return getName ();
}
@Override
public List<OperationInputType> getInputs() {
return new ArrayList<OperationInputType> ();
}
@Override
public String getDescription(Locale locale) {
return getName ();
}
@Override
public OperationExecuter createExecuter(Object operationProperties,
MapperContext context) {
return null;
}
};
}
private static InputOperationDTO createInputOperation (final String attributeName, final AttributeType attributeType) {
final InputOperationDTO op = new InputOperationDTO (null, attributeName, attributeType);
return op;
}
private static TransformOperationDTO createTransformOperation (final PropertyClass properties, final OperationDTO ... inputs) {
final List<OperationInputDTO> opInputs = new ArrayList<OperationInputDTO> ();
for (final OperationDTO input: inputs) {
opInputs.add (new OperationInputDTO (input));
}
return new TransformOperationDTO (
createOperationType (),
opInputs,
properties
);
}
private static OperationType createOperationType () {
return new OperationType() {
@Override
public boolean equals (final Object o) {
if (o == null || !(o instanceof OperationType)) {
return false;
}
return getName ().equals (((OperationType)o).getName ());
}
@Override
public String toString () {
return String.format ("OperationType(%s)", getName ());
}
@Override
public Type getReturnType() {
return String.class;
}
@Override
public Class<?> getPropertyBeanClass () {
return PropertyClass.class;
}
@Override
public String getName () {
return "testTransformOperation";
}
@Override
public String getLabel (final Locale locale) {
return getName ();
}
@Override
public String getFormatLabel (final Locale locale) {
return getName ();
}
@Override
public List<OperationInputType> getInputs() {
final List<OperationInputType> inputs = new ArrayList<OperationInputType> ();
inputs.add (new OperationInputType () {
@Override
public String getName () {
return "input";
}
@Override
public Type getInputType () {
return Object.class;
}
@Override
public String getDescription (final Locale locale) {
return getName ();
}
@Override
public boolean isVariableInputCount () {
return true;
}
});
return inputs;
}
@Override
public String getDescription (final Locale locale) {
return getName ();
}
@Override
public OperationExecuter createExecuter (final Object operationProperties,
final MapperContext context) {
return null;
}
};
}
private static FeatureTypeAttribute createFeatureTypeAttribute (final String name, final AttributeType type) {
return new FeatureTypeAttribute () {
@Override
public boolean equals (final Object o) {
if (o == null || !(o instanceof FeatureTypeAttribute)) {
return false;
}
return getName ().equals (((FeatureTypeAttribute)o).getName ());
}
@Override
public String toString () {
return String.format ("FeatureTypeAttribute(%s: %s)", name, type);
}
@Override
public int compareTo (FeatureTypeAttribute o) {
return getName ().compareTo (o.getName ());
}
@Override
public AttributeType getType() {
return type;
}
@Override
public QName getName() {
return new QName () {
@Override
public int compareTo(QName o) {
return getLocalPart ().compareTo (o.getLocalPart ());
}
@Override
public String getNamespace() {
return "http://www.idgis.nl";
}
@Override
public String getLocalPart() {
return name;
}
};
}
};
}
}