code: package it.unibz.inf.ontop.model.type.impl;
  
  import com.google.common.collect.ImmutableList;
  import it.unibz.inf.ontop.exception.OntopInternalBugException;
  import it.unibz.inf.ontop.model.type.ConcreteNumericRDFDatatype;
  import it.unibz.inf.ontop.model.type.TypePropagationSubstitutionHierarchy;
  import it.unibz.inf.ontop.utils.ImmutableCollectors;
  
  import java.util.stream.Stream;
  
  
  public class TypePropagationSubstitutionHierarchyImpl extends TermTypeHierarchyImpl<ConcreteNumericRDFDatatype>
          implements TypePropagationSubstitutionHierarchy {
  
      protected TypePropagationSubstitutionHierarchyImpl(ConcreteNumericRDFDatatype topDatatype) {
          this(ImmutableList.of(topDatatype));
      }
  
      private TypePropagationSubstitutionHierarchyImpl(ImmutableList<ConcreteNumericRDFDatatype> types) {
          super(types);
      }
  
      @Override
      public ConcreteNumericRDFDatatype getClosestCommonType(TypePropagationSubstitutionHierarchy otherHierarchy) {
          return getClosestCommonTermType(otherHierarchy)
                  .orElseThrow(DifferentTopPropagatedNumericTypeException::new);
      }
  
      @Override
      public TypePropagationSubstitutionHierarchy newHierarchy(ConcreteNumericRDFDatatype childType) {
          return new TypePropagationSubstitutionHierarchyImpl(
                  Stream.concat(Stream.of(childType), getTermTypes()) // most preferable for promotion type first
                      .collect(ImmutableCollectors.toList()));
      }
  
      /**
       * Internal bug: all the concrete numeric types must be convertible into xsd:double
       */
      private static class DifferentTopPropagatedNumericTypeException extends OntopInternalBugException {
  
          private DifferentTopPropagatedNumericTypeException() {
              super("Internal bug: all the concrete numeric types must be convertible into xsd:double");
          }
      }
  }
  