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);
      }
    }
  }
 private void parseConstructor(ATypeTag typeTag, IAType objectType, DataOutput out)
     throws AsterixException, AdmLexerException, IOException {
   final ATypeTag targetTypeTag = getTargetTypeTag(typeTag, objectType);
   if (targetTypeTag != null) {
     DataOutput dataOutput = out;
     if (targetTypeTag != typeTag) {
       castBuffer.reset();
       dataOutput = castBuffer.getDataOutput();
     }
     int token = admLexer.next();
     if (token == AdmLexer.TOKEN_CONSTRUCTOR_OPEN) {
       token = admLexer.next();
       if (token == AdmLexer.TOKEN_STRING_LITERAL) {
         final String unquoted =
             admLexer.getLastTokenImage().substring(1, admLexer.getLastTokenImage().length() - 1);
         if (!parseValue(unquoted, typeTag, dataOutput)) {
           throw new ParseException(
               "Missing deserializer method for constructor: "
                   + AdmLexer.tokenKindToString(token)
                   + ".");
         }
         token = admLexer.next();
         if (token == AdmLexer.TOKEN_CONSTRUCTOR_CLOSE) {
           if (targetTypeTag != typeTag) {
             ITypeConvertComputer promoteComputer =
                 ATypeHierarchy.getTypePromoteComputer(typeTag, targetTypeTag);
             // the availability if the promote computer should be consistent with the availability
             // of a target type
             assert promoteComputer != null;
             // do the promotion; note that the type tag field should be skipped
             promoteComputer.convertType(
                 castBuffer.getByteArray(),
                 castBuffer.getStartOffset() + 1,
                 castBuffer.getLength() - 1,
                 out);
           }
           return;
         }
       }
     }
   }
   throw new ParseException(
       mismatchErrorMessage + objectType.getTypeName() + ". Got " + typeTag + " instead.");
 }
 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);
          }
        }
      }
    }
  }