code: package com.taxonic.carml.engine;
  
  import com.google.common.collect.ImmutableList;
  import com.google.common.collect.ImmutableSet;
  import com.taxonic.carml.logical_source_resolver.LogicalSourceResolver;
  import org.apache.commons.lang3.tuple.Pair;
  import org.eclipse.rdf4j.model.IRI;
  import org.eclipse.rdf4j.model.Resource;
  import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
  import org.junit.Before;
  import org.junit.Rule;
  import org.junit.Test;
  import org.mockito.Mock;
  import org.mockito.junit.MockitoJUnit;
  import org.mockito.junit.MockitoRule;
  
  import java.util.Arrays;
  import java.util.Optional;
  import java.util.Set;
  import java.util.function.Supplier;
  
  import static org.hamcrest.MatcherAssert.assertThat;
  import static org.hamcrest.collection.IsIn.in;
  import static org.hamcrest.core.Is.is;
  import static org.mockito.Mockito.when;
  
  public class ParentTriplesMapperTest {
  	
  	@Mock
  	private TermGenerator<Resource> subjectGenerator;
  	
  	@Mock
  	private Supplier<Iterable<Object>> getIterator;
  	
  	@Mock
  	private LogicalSourceResolver.ExpressionEvaluatorFactory<Object> expressionEvaluatorFactory;
  
  	@Mock
  	EvaluateExpression evaluate;
  
  	@Rule
  	public MockitoRule mockitoRule = MockitoJUnit.rule();
  	
  	Set<Pair<String, Object>> joinValues =
  			ImmutableSet.of(
  				Pair.of("country.name", "Belgium")
  			);
  
  	Set<Pair<String, Object>> multiJoinValues =
  			ImmutableSet.of(
  				Pair.of("country.name", Arrays.asList("Belgium", null, "Netherlands"))
  			);
  
  	String entry = 
  			"{\r\n" + 
  			"\"food\": {\r\n" + 
  			"	\"name\": \"Belgian Waffles\",\r\n" + 
  			"	\"countryOfOrigin\": \"Belgium\"\r\n" + 
  			"	}\r\n" + 
  			"}";
  
  	IRI belgianWaffles = SimpleValueFactory.getInstance().createIRI("http://example.org/food/BelgianWaffles");
  
  	String countryNameField = "country.name";
  
  	ParentTriplesMapper<Object> mapper;
  
  	@Before
  	public void setup() {
  		mapper = new ParentTriplesMapper<>(subjectGenerator, getIterator, expressionEvaluatorFactory);
  		when(getIterator.get()).thenReturn(ImmutableList.of(entry));
  		when(expressionEvaluatorFactory.apply(entry)).thenReturn(evaluate);
  		when(subjectGenerator.apply(evaluate)).thenReturn(ImmutableList.of(belgianWaffles));
  	}
  
  	@Test
  	public void parentTriplesMapper_givenJoinConditions() {
  		when(evaluate.apply(countryNameField)).thenReturn(Optional.of("Belgium"));
  		Set<Resource> resources = mapper.map(joinValues);
  		assertThat(resources.size(), is(1));
  		assertThat(belgianWaffles, is(in(resources)));
  	}
  
  	@Test
  	public void parentTriplesMapper_givenMultiJoinWithNullValues_ShouldStillResolveJoin() {
  		when(evaluate.apply(countryNameField)).thenReturn(Optional.of("Belgium"));
  		Set<Resource> resources = mapper.map(multiJoinValues);
  		assertThat(resources.size(), is(1));
  		assertThat(belgianWaffles, is(in(resources)));
  	}
  
  	@Test
  	public void parentTriplesMapper_givenMultipleParentValues_succeeds() {
  		when(evaluate.apply(countryNameField)).thenReturn(Optional.of(ImmutableSet.of("Belgium", "Germany")));
  		Set<Resource> resources = mapper.map(multiJoinValues);
  		assertThat(resources.size(), is(1));
  		assertThat(belgianWaffles, is(in(resources)));
  	}
  
  	@Test
  	public void parentTriplesMapper_givenMultipleParentValues_fails() {
  		when(evaluate.apply(countryNameField)).thenReturn(Optional.of(ImmutableSet.of("Norway", "Germany")));
  		Set<Resource> resources = mapper.map(multiJoinValues);
  		assertThat(resources.size(), is(0));
  	}
  
  	// TODO
  	public void parentTriplesMapper_notGivenJoinConditions() {
  		
  	}
  }
  