code: private ImmutableList<TermType> inferCastTypes(
              Predicate predicate, Collection<CQIE> samePredicateRules,
              ImmutableMap<CQIE, ImmutableList<Optional<TermType>>> termTypeMap,
              Map<Predicate, ImmutableList<TermType>> alreadyKnownCastTypes, DBMetadata metadata) {
  
          if (samePredicateRules.isEmpty()) {
  
              ImmutableList.Builder<TermType> defaultTypeBuilder = ImmutableList.builder();
  
              RelationID tableId = relation2Predicate.createRelationFromPredicateName(metadata.getQuotedIDFactory(), predicate);
              Optional<RelationDefinition> td = Optional.ofNullable(metadata.getRelation(tableId));
  
              IntStream.range(0, predicate.getArity())
                      .forEach(i -> {
  
                          if(td.isPresent()) {
                              Attribute attribute = td.get().getAttribute(i+1);
  
                              //get type from metadata
                              defaultTypeBuilder.add(attribute.getTermType());
                          }
                          else{
                              defaultTypeBuilder.add(literalType);
                          }});
              return defaultTypeBuilder.build();
          }
  
          ImmutableMultimap<Integer, TermType> collectedProposedCastTypes = collectProposedCastTypes(
                  samePredicateRules, termTypeMap, alreadyKnownCastTypes);
  
          return collectedProposedCastTypes.keySet().stream()
                  // 0 to n
                  .sorted()
                  .map(i -> collectedProposedCastTypes.get(i).stream()
                              .reduce(
                                      // Neutral
                                      null,
                                      (type1, type2) -> type1 == null ? type2 : unifyCastTypes(type1, type2)))
                  .map(type -> {
                      if (type != null) {
                          return type;
                      }
                      throw new IllegalStateException("Every argument is expected to have a COL_TYPE");
                  })
                  .collect(ImmutableCollectors.toList());
      }
docs: Infers the cast types for one intensional predicate
  
  No side-effect on alreadyKnownCastTypes