code: package com.taxonic.carml.rdf_mapper.impl;
  
  import java.lang.reflect.Type;
  import java.util.List;
  import java.util.Optional;
  import java.util.Set;
  import java.util.stream.Collectors;
  
  import org.eclipse.rdf4j.model.IRI;
  import org.eclipse.rdf4j.model.Model;
  import org.eclipse.rdf4j.model.Resource;
  import org.eclipse.rdf4j.model.vocabulary.RDF;
  import com.google.common.collect.ImmutableSet;
  import com.taxonic.carml.rdf_mapper.Mapper;
  import com.taxonic.carml.rdf_mapper.TypeDecider;
  
  public class TypeFromTripleTypeDecider implements TypeDecider {
  
  	private Mapper mapper;
  	private Optional<TypeDecider> propertyTypeDecider;
  	
  	public TypeFromTripleTypeDecider(Mapper mapper) {
  		this(mapper, Optional.empty());
  	}
  	
  	public TypeFromTripleTypeDecider(Mapper mapper, Optional<TypeDecider> propertyTypeDecider) {
  		this.mapper = mapper;
  		this.propertyTypeDecider = propertyTypeDecider;
  	}
  
  	@Override
  	public Set<Type> decide(Model model, Resource resource) {
  		
  		List<IRI> rdfTypes =
  			model.filter(resource, RDF.TYPE, null).objects().stream()
  				.map(v -> (IRI) v)
  				.collect(Collectors.toList());
  		
  		// TODO what if multiple rdf:types? probably choose the only 1 that's known/registered. what if multiple of those?
  		if (rdfTypes.size() > 1)
  			return rdfTypes.stream()
  					.map(mapper::getDecidableType)
  					.collect(Collectors.toSet());
  		
  		// if no rdf:type, use property type (or its registered implementation) as target type
  		if (rdfTypes.isEmpty()) {
  			if(propertyTypeDecider.isPresent()) {
  				return propertyTypeDecider.get().decide(model, resource);
  			} else {
  				throw new RuntimeException(String.format("No decidable type found for %s. Register decidable type on rdf mapper.", resource));
  			}
  		}
  		
  		IRI rdfType = rdfTypes.get(0);
  		return ImmutableSet.of(mapper.getDecidableType(rdfType));
  	}
  
  }
  