private ATypeTag getTargetTypeTag(ATypeTag expectedTypeTag, IAType aObjectType)
     throws IOException {
   if (aObjectType == null) {
     return expectedTypeTag;
   }
   if (aObjectType.getTypeTag() != ATypeTag.UNION) {
     final ATypeTag typeTag = aObjectType.getTypeTag();
     if (ATypeHierarchy.canPromote(expectedTypeTag, typeTag)
         || ATypeHierarchy.canDemote(expectedTypeTag, typeTag)) {
       return typeTag;
     } else {
       return null;
     }
     //            return ATypeHierarchy.canPromote(expectedTypeTag, typeTag) ? typeTag : null;
   } else { // union
     List<IAType> unionList = ((AUnionType) aObjectType).getUnionList();
     for (IAType t : unionList) {
       final ATypeTag typeTag = t.getTypeTag();
       if (ATypeHierarchy.canPromote(expectedTypeTag, typeTag)
           || ATypeHierarchy.canDemote(expectedTypeTag, typeTag)) {
         return typeTag;
       }
     }
   }
   return null;
 }
  private void parseAndCastNumeric(ATypeTag typeTag, IAType objectType, DataOutput out)
      throws AsterixException, IOException {
    final ATypeTag targetTypeTag = getTargetTypeTag(typeTag, objectType);
    DataOutput dataOutput = out;
    if (targetTypeTag != typeTag) {
      castBuffer.reset();
      dataOutput = castBuffer.getDataOutput();
    }

    if (targetTypeTag == null || !parseValue(admLexer.getLastTokenImage(), typeTag, dataOutput)) {
      throw new ParseException(
          mismatchErrorMessage + objectType.getTypeName() + mismatchErrorMessage2 + typeTag);
    }

    // If two type tags are not the same, either we try to promote or demote source type to the
    // target type
    if (targetTypeTag != typeTag) {
      if (ATypeHierarchy.canPromote(typeTag, targetTypeTag)) {
        // can promote typeTag to targetTypeTag
        ITypeConvertComputer promoteComputer =
            ATypeHierarchy.getTypePromoteComputer(typeTag, targetTypeTag);
        if (promoteComputer == null) {
          throw new AsterixException(
              "Can't cast the " + typeTag + " type to the " + targetTypeTag + " type.");
        }
        // do the promotion; note that the type tag field should be skipped
        promoteComputer.convertType(
            castBuffer.getByteArray(),
            castBuffer.getStartOffset() + 1,
            castBuffer.getLength() - 1,
            out);
      } else if (ATypeHierarchy.canDemote(typeTag, targetTypeTag)) {
        // can demote source type to the target type
        ITypeConvertComputer demoteComputer =
            ATypeHierarchy.getTypeDemoteComputer(typeTag, targetTypeTag);
        if (demoteComputer == null) {
          throw new AsterixException(
              "Can't cast the " + typeTag + " type to the " + targetTypeTag + " type.");
        }
        // do the demotion; note that the type tag field should be skipped
        demoteComputer.convertType(
            castBuffer.getByteArray(),
            castBuffer.getStartOffset() + 1,
            castBuffer.getLength() - 1,
            out);
      }
    }
  }
 protected void processDataValues(IFrameTupleReference tuple) throws AlgebricksException {
   if (skipStep()) {
     return;
   }
   inputVal.reset();
   eval.evaluate(tuple);
   ATypeTag typeTag =
       EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
   if (typeTag == ATypeTag.NULL) {
     processNull();
     return;
   } else if (aggType == ATypeTag.SYSTEM_NULL) {
     aggType = typeTag;
   } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
     throw new AlgebricksException(
         "Unexpected type "
             + typeTag
             + " in aggregation input stream. Expected type "
             + aggType
             + ".");
   } else if (ATypeHierarchy.canPromote(aggType, typeTag)) {
     aggType = typeTag;
   }
   ++count;
   switch (typeTag) {
     case INT8:
       {
         byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
         sum += val;
         break;
       }
     case INT16:
       {
         short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
         sum += val;
         break;
       }
     case INT32:
       {
         int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
         sum += val;
         break;
       }
     case INT64:
       {
         long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
         sum += val;
         break;
       }
     case FLOAT:
       {
         float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
         sum += val;
         break;
       }
     case DOUBLE:
       {
         double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
         sum += val;
         break;
       }
     default:
       {
         throw new NotImplementedException("Cannot compute AVG for values of type " + typeTag);
       }
   }
   inputVal.reset();
 }
  @Override
  public void step(IFrameTupleReference tuple) throws AlgebricksException {
    inputVal.reset();
    eval.evaluate(tuple);
    ATypeTag typeTag =
        EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
    if (typeTag == ATypeTag.NULL) {
      processNull();
      return;
    } else if (aggType == ATypeTag.NULL) {
      return;
    } else if (aggType == ATypeTag.SYSTEM_NULL) {
      if (typeTag == ATypeTag.SYSTEM_NULL) {
        // Ignore.
        return;
      }
      // First value encountered. Set type, comparator, and initial value.
      aggType = typeTag;
      // Set comparator.
      IBinaryComparatorFactory cmpFactory =
          AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(aggType, isMin);
      cmp = cmpFactory.createBinaryComparator();
      // Initialize min value.
      outputVal.assign(inputVal);
    } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
      throw new AlgebricksException(
          "Unexpected type "
              + typeTag
              + " in aggregation input stream. Expected type "
              + aggType
              + ".");
    } else {

      // If a system_null is encountered locally, it would be an error; otherwise if it is seen
      // by a global aggregator, it is simple ignored.
      if (typeTag == ATypeTag.SYSTEM_NULL) {
        processSystemNull();
        return;
      }

      if (ATypeHierarchy.canPromote(aggType, typeTag)) {
        tpc = ATypeHierarchy.getTypePromoteComputer(aggType, typeTag);
        aggType = typeTag;
        cmp =
            AqlBinaryComparatorFactoryProvider.INSTANCE
                .getBinaryComparatorFactory(aggType, isMin)
                .createBinaryComparator();
        if (tpc != null) {
          tempValForCasting.reset();
          try {
            tpc.convertType(
                outputVal.getByteArray(),
                outputVal.getStartOffset() + 1,
                outputVal.getLength() - 1,
                tempValForCasting.getDataOutput());
          } catch (IOException e) {
            throw new AlgebricksException(e);
          }
          outputVal.reset();
          outputVal.assign(tempValForCasting);
        }
        try {
          if (cmp.compare(
                  inputVal.getByteArray(),
                  inputVal.getStartOffset(),
                  inputVal.getLength(),
                  outputVal.getByteArray(),
                  outputVal.getStartOffset(),
                  outputVal.getLength())
              < 0) {
            outputVal.assign(inputVal);
          }
        } catch (HyracksDataException e) {
          throw new AlgebricksException(e);
        }

      } else {
        tpc = ATypeHierarchy.getTypePromoteComputer(typeTag, aggType);
        if (tpc != null) {
          tempValForCasting.reset();
          try {
            tpc.convertType(
                inputVal.getByteArray(),
                inputVal.getStartOffset() + 1,
                inputVal.getLength() - 1,
                tempValForCasting.getDataOutput());
          } catch (IOException e) {
            throw new AlgebricksException(e);
          }
          try {
            if (cmp.compare(
                    tempValForCasting.getByteArray(),
                    tempValForCasting.getStartOffset(),
                    tempValForCasting.getLength(),
                    outputVal.getByteArray(),
                    outputVal.getStartOffset(),
                    outputVal.getLength())
                < 0) {
              outputVal.assign(tempValForCasting);
            }
          } catch (HyracksDataException e) {
            throw new AlgebricksException(e);
          }
        } else {
          try {
            if (cmp.compare(
                    inputVal.getByteArray(),
                    inputVal.getStartOffset(),
                    inputVal.getLength(),
                    outputVal.getByteArray(),
                    outputVal.getStartOffset(),
                    outputVal.getLength())
                < 0) {
              outputVal.assign(inputVal);
            }
          } catch (HyracksDataException e) {
            throw new AlgebricksException(e);
          }
        }
      }
    }
  }