public static Optional getWiderType()

in nifi-commons/nifi-record/src/main/java/org/apache/nifi/serialization/record/util/DataTypeUtils.java [1680:1791]


    public static Optional<DataType> getWiderType(final DataType thisDataType, final DataType otherDataType) {
        if (thisDataType == null) {
            return Optional.ofNullable(otherDataType);
        }
        if (otherDataType == null) {
            return Optional.of(thisDataType);
        }

        final RecordFieldType thisFieldType = thisDataType.getFieldType();
        final RecordFieldType otherFieldType = otherDataType.getFieldType();

        if (thisFieldType == RecordFieldType.ARRAY && otherFieldType == RecordFieldType.ARRAY) {
            // Check for array<null> and return the other (or empty if they are both array<null>). This happens if at some point we inferred an element type of null which
            // indicates an empty array, and then we inferred a non-null type for the same field in a different record. The non-null type should be used in that case.
            ArrayDataType thisArrayType = (ArrayDataType) thisDataType;
            ArrayDataType otherArrayType = (ArrayDataType) otherDataType;
            if (thisArrayType.getElementType() == null) {
                if (otherArrayType.getElementType() == null) {
                    return Optional.empty();
                } else {
                    return Optional.of(otherDataType);
                }
            } else {
                if (otherArrayType.getElementType() == null) {
                    return Optional.of(thisDataType);
                } else {
                    final Optional<DataType> widerElementType = getWiderType(thisArrayType.getElementType(), otherArrayType.getElementType());
                    if (widerElementType.isPresent()) {
                        return Optional.of(RecordFieldType.ARRAY.getArrayDataType(widerElementType.get()));
                    }
                    return Optional.empty();
                }
            }
        }

        final int thisIntTypeValue = getIntegerTypeValue(thisFieldType);
        final int otherIntTypeValue = getIntegerTypeValue(otherFieldType);
        final boolean thisIsInt = thisIntTypeValue > -1;
        final boolean otherIsInt = otherIntTypeValue > -1;

        if (thisIsInt && otherIsInt) {
            if (thisIntTypeValue > otherIntTypeValue) {
                return Optional.of(thisDataType);
            }

            return Optional.of(otherDataType);
        }

        final boolean otherIsDecimal = isDecimalType(otherFieldType);

        switch (thisFieldType) {
            case BYTE:
            case SHORT:
            case INT:
            case LONG:
                if (otherIsDecimal) {
                    return Optional.of(otherDataType);
                }
                break;
            case FLOAT:
                if (otherFieldType == RecordFieldType.DOUBLE || otherFieldType == RecordFieldType.DECIMAL) {
                    return Optional.of(otherDataType);
                }
                if (otherFieldType == RecordFieldType.BYTE || otherFieldType == RecordFieldType.SHORT || otherFieldType == RecordFieldType.INT || otherFieldType == RecordFieldType.LONG) {
                    return Optional.of(thisDataType);
                }
                break;
            case DOUBLE:
                if (otherFieldType == RecordFieldType.DECIMAL) {
                    return Optional.of(otherDataType);
                }
                if (otherFieldType == RecordFieldType.BYTE || otherFieldType == RecordFieldType.SHORT || otherFieldType == RecordFieldType.INT || otherFieldType == RecordFieldType.LONG
                    || otherFieldType == RecordFieldType.FLOAT) {

                    return Optional.of(thisDataType);
                }
                break;
            case DECIMAL:
                if (otherFieldType == RecordFieldType.DOUBLE || otherFieldType == RecordFieldType.FLOAT || otherIsInt) {
                    return Optional.of(thisDataType);
                } else if (otherFieldType == RecordFieldType.DECIMAL) {
                    final DecimalDataType thisDecimalDataType = (DecimalDataType) thisDataType;
                    final DecimalDataType otherDecimalDataType = (DecimalDataType) otherDataType;

                    final int precision = Math.max(thisDecimalDataType.getPrecision(), otherDecimalDataType.getPrecision());
                    final int scale = Math.max(thisDecimalDataType.getScale(), otherDecimalDataType.getScale());
                    return Optional.of(RecordFieldType.DECIMAL.getDecimalDataType(precision, scale));
                }
                break;
            case CHAR:
            case UUID:
                if (otherFieldType == RecordFieldType.STRING) {
                    return Optional.of(otherDataType);
                }
                break;
            case STRING:
                if (otherFieldType == RecordFieldType.CHAR || otherFieldType == RecordFieldType.UUID) {
                    return Optional.of(thisDataType);
                }
                break;
            case RECORD:
                if (otherFieldType != RecordFieldType.RECORD)  {
                    return Optional.empty();
                }

                final RecordDataType thisRecordDataType = (RecordDataType) thisDataType;
                final RecordDataType otherRecordDataType = (RecordDataType) otherDataType;
                return getWiderRecordType(thisRecordDataType, otherRecordDataType);
        }

        return Optional.empty();
    }