| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.vxquery.runtime.functions.util; |
| |
| import java.io.DataOutput; |
| |
| import org.apache.vxquery.context.DynamicContext; |
| import org.apache.vxquery.datamodel.accessors.TaggedValuePointable; |
| import org.apache.vxquery.datamodel.accessors.TypedPointables; |
| import org.apache.vxquery.datamodel.values.ValueTag; |
| import org.apache.vxquery.exceptions.ErrorCode; |
| import org.apache.vxquery.exceptions.SystemException; |
| import org.apache.vxquery.runtime.functions.arithmetic.AbstractArithmeticOperation; |
| import org.apache.vxquery.runtime.functions.cast.CastToDoubleOperation; |
| import org.apache.vxquery.types.BuiltinTypeConstants; |
| import org.apache.vxquery.types.BuiltinTypeRegistry; |
| |
| import org.apache.hyracks.data.std.api.IPointable; |
| import org.apache.hyracks.data.std.primitive.DoublePointable; |
| import org.apache.hyracks.data.std.primitive.LongPointable; |
| import org.apache.hyracks.data.std.util.ArrayBackedValueStorage; |
| |
| public class ArithmeticHelper { |
| private final AbstractArithmeticOperation aOp; |
| private final DynamicContext dCtx; |
| private final TypedPointables tp1; |
| private final TypedPointables tp2; |
| private final ArrayBackedValueStorage abvs; |
| private final DataOutput dOut; |
| private final ArrayBackedValueStorage abvsArgument1; |
| private final DataOutput dOutArgument1; |
| private final ArrayBackedValueStorage abvsArgument2; |
| private final DataOutput dOutArgument2; |
| private final CastToDoubleOperation castToDouble; |
| |
| public ArithmeticHelper(AbstractArithmeticOperation aOp, DynamicContext dCtx) { |
| this.aOp = aOp; |
| this.dCtx = dCtx; |
| tp1 = new TypedPointables(); |
| tp2 = new TypedPointables(); |
| abvs = new ArrayBackedValueStorage(); |
| dOut = abvs.getDataOutput(); |
| abvsArgument1 = new ArrayBackedValueStorage(); |
| dOutArgument1 = abvsArgument1.getDataOutput(); |
| abvsArgument2 = new ArrayBackedValueStorage(); |
| dOutArgument2 = abvsArgument2.getDataOutput(); |
| castToDouble = new CastToDoubleOperation(); |
| } |
| |
| public void compute(TaggedValuePointable tvp1, TaggedValuePointable tvp2, IPointable result) |
| throws SystemException { |
| abvs.reset(); |
| try { |
| int tid1 = getBaseTypeForArithmetics(tvp1.getTag()); |
| int tid2 = getBaseTypeForArithmetics(tvp2.getTag()); |
| LongPointable longp1 = (LongPointable) LongPointable.FACTORY.createPointable(); |
| DoublePointable doublep1 = (DoublePointable) DoublePointable.FACTORY.createPointable(); |
| switch (tvp1.getTag()) { |
| case ValueTag.XS_INTEGER_TAG: |
| case ValueTag.XS_NON_POSITIVE_INTEGER_TAG: |
| case ValueTag.XS_NEGATIVE_INTEGER_TAG: |
| case ValueTag.XS_LONG_TAG: |
| case ValueTag.XS_NON_NEGATIVE_INTEGER_TAG: |
| case ValueTag.XS_UNSIGNED_LONG_TAG: |
| case ValueTag.XS_POSITIVE_INTEGER_TAG: |
| case ValueTag.XS_INT_TAG: |
| case ValueTag.XS_UNSIGNED_INT_TAG: |
| case ValueTag.XS_SHORT_TAG: |
| case ValueTag.XS_UNSIGNED_SHORT_TAG: |
| case ValueTag.XS_BYTE_TAG: |
| case ValueTag.XS_UNSIGNED_BYTE_TAG: |
| abvsArgument1.reset(); |
| FunctionHelper.getIntegerPointable(tvp1, dOutArgument1, tp1); |
| longp1.set(abvsArgument1.getByteArray(), abvsArgument1.getStartOffset() + 1, |
| LongPointable.TYPE_TRAITS.getFixedLength()); |
| break; |
| case ValueTag.XS_DOUBLE_TAG: |
| tvp1.getValue(doublep1); |
| break; |
| case ValueTag.XS_UNTYPED_ATOMIC_TAG: |
| tid1 = ValueTag.XS_DOUBLE_TAG; |
| tvp1.getValue(tp1.utf8sp); |
| abvsArgument1.reset(); |
| castToDouble.convertUntypedAtomic(tp1.utf8sp, dOutArgument1); |
| doublep1.set(abvsArgument1.getByteArray(), abvsArgument1.getStartOffset() + 1, |
| DoublePointable.TYPE_TRAITS.getFixedLength()); |
| break; |
| } |
| LongPointable longp2 = (LongPointable) LongPointable.FACTORY.createPointable(); |
| DoublePointable doublep2 = (DoublePointable) DoublePointable.FACTORY.createPointable(); |
| switch (tvp2.getTag()) { |
| case ValueTag.XS_INTEGER_TAG: |
| case ValueTag.XS_NON_POSITIVE_INTEGER_TAG: |
| case ValueTag.XS_NEGATIVE_INTEGER_TAG: |
| case ValueTag.XS_LONG_TAG: |
| case ValueTag.XS_NON_NEGATIVE_INTEGER_TAG: |
| case ValueTag.XS_UNSIGNED_LONG_TAG: |
| case ValueTag.XS_POSITIVE_INTEGER_TAG: |
| case ValueTag.XS_INT_TAG: |
| case ValueTag.XS_UNSIGNED_INT_TAG: |
| case ValueTag.XS_SHORT_TAG: |
| case ValueTag.XS_UNSIGNED_SHORT_TAG: |
| case ValueTag.XS_BYTE_TAG: |
| case ValueTag.XS_UNSIGNED_BYTE_TAG: |
| abvsArgument2.reset(); |
| FunctionHelper.getIntegerPointable(tvp2, dOutArgument2, tp2); |
| longp2.set(abvsArgument2.getByteArray(), abvsArgument2.getStartOffset() + 1, |
| LongPointable.TYPE_TRAITS.getFixedLength()); |
| break; |
| case ValueTag.XS_DOUBLE_TAG: |
| tvp2.getValue(doublep2); |
| break; |
| case ValueTag.XS_UNTYPED_ATOMIC_TAG: |
| tid2 = ValueTag.XS_DOUBLE_TAG; |
| tvp2.getValue(tp2.utf8sp); |
| abvsArgument2.reset(); |
| castToDouble.convertUntypedAtomic(tp2.utf8sp, dOutArgument2); |
| doublep2.set(abvsArgument2.getByteArray(), abvsArgument2.getStartOffset() + 1, |
| DoublePointable.TYPE_TRAITS.getFixedLength()); |
| break; |
| } |
| switch (tid1) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp1.getValue(tp1.decp); |
| switch (tid2) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp2.getValue(tp2.decp); |
| aOp.operateDecimalDecimal(tp1.decp, tp2.decp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| aOp.operateDecimalInteger(tp1.decp, longp2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp2.getValue(tp2.floatp); |
| aOp.operateDecimalFloat(tp1.decp, tp2.floatp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| aOp.operateDecimalDouble(tp1.decp, doublep2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateDecimalDTDuration(tp1.decp, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateDecimalYMDuration(tp1.decp, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| switch (tid2) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp2.getValue(tp2.decp); |
| aOp.operateIntegerDecimal(longp1, tp2.decp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| aOp.operateIntegerInteger(longp1, longp2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp2.getValue(tp2.floatp); |
| aOp.operateIntegerFloat(longp1, tp2.floatp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| aOp.operateIntegerDouble(longp1, doublep2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateIntegerDTDuration(longp1, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateIntegerYMDuration(longp1, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp1.getValue(tp1.floatp); |
| switch (tid2) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp2.getValue(tp2.decp); |
| aOp.operateFloatDecimal(tp1.floatp, tp2.decp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| aOp.operateFloatInteger(tp1.floatp, longp2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp2.getValue(tp2.floatp); |
| aOp.operateFloatFloat(tp1.floatp, tp2.floatp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| aOp.operateFloatDouble(tp1.floatp, doublep2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateFloatDTDuration(tp1.floatp, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateFloatYMDuration(tp1.floatp, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| switch (tid2) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp2.getValue(tp2.decp); |
| aOp.operateDoubleDecimal(doublep1, tp2.decp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| aOp.operateDoubleInteger(doublep1, longp2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp2.getValue(tp2.floatp); |
| aOp.operateDoubleFloat(doublep1, tp2.floatp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| aOp.operateDoubleDouble(doublep1, doublep2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateDoubleDTDuration(doublep1, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateDoubleYMDuration(doublep1, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_DATE_TAG: |
| tvp1.getValue(tp1.datep); |
| switch (tid2) { |
| case ValueTag.XS_DATE_TAG: |
| tvp2.getValue(tp2.datep); |
| aOp.operateDateDate(tp1.datep, tp2.datep, dCtx, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateDateDTDuration(tp1.datep, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateDateYMDuration(tp1.datep, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_DATETIME_TAG: |
| tvp1.getValue(tp1.datetimep); |
| switch (tid2) { |
| case ValueTag.XS_DATETIME_TAG: |
| tvp2.getValue(tp2.datetimep); |
| aOp.operateDatetimeDatetime(tp1.datetimep, tp2.datetimep, dCtx, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateDatetimeDTDuration(tp1.datetimep, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateDatetimeYMDuration(tp1.datetimep, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_TIME_TAG: |
| tvp1.getValue(tp1.timep); |
| switch (tid2) { |
| case ValueTag.XS_TIME_TAG: |
| tvp2.getValue(tp2.timep); |
| aOp.operateTimeTime(tp1.timep, tp2.timep, dCtx, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateTimeDTDuration(tp1.timep, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| } |
| break; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp1.getValue(tp1.longp); |
| switch (tid2) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp2.getValue(tp2.decp); |
| aOp.operateDTDurationDecimal(tp1.longp, tp2.decp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| aOp.operateDTDurationInteger(tp1.longp, longp2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp2.getValue(tp2.floatp); |
| aOp.operateDTDurationFloat(tp1.longp, tp2.floatp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| aOp.operateDTDurationDouble(tp1.longp, doublep2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DATE_TAG: |
| tvp2.getValue(tp2.datep); |
| aOp.operateDTDurationDate(tp1.longp, tp2.datep, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_TIME_TAG: |
| tvp2.getValue(tp2.timep); |
| aOp.operateDTDurationTime(tp1.longp, tp2.timep, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DATETIME_TAG: |
| tvp2.getValue(tp2.datetimep); |
| aOp.operateDTDurationDatetime(tp1.longp, tp2.datetimep, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| tvp2.getValue(tp2.longp); |
| aOp.operateDTDurationDTDuration(tp1.longp, tp2.longp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp1.getValue(tp1.intp); |
| switch (tid2) { |
| case ValueTag.XS_DECIMAL_TAG: |
| tvp2.getValue(tp2.decp); |
| aOp.operateYMDurationDecimal(tp1.intp, tp2.decp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_INTEGER_TAG: |
| aOp.operateYMDurationInteger(tp1.intp, longp2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_FLOAT_TAG: |
| tvp2.getValue(tp2.floatp); |
| aOp.operateYMDurationFloat(tp1.intp, tp2.floatp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DOUBLE_TAG: |
| aOp.operateYMDurationDouble(tp1.intp, doublep2, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DATE_TAG: |
| tvp2.getValue(tp2.datep); |
| aOp.operateYMDurationDate(tp1.intp, tp2.datep, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_DATETIME_TAG: |
| tvp2.getValue(tp2.datetimep); |
| aOp.operateYMDurationDatetime(tp1.intp, tp2.datetimep, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| tvp2.getValue(tp2.intp); |
| aOp.operateYMDurationYMDuration(tp1.intp, tp2.intp, dOut); |
| result.set(abvs.getByteArray(), 0, abvs.getLength()); |
| return; |
| } |
| break; |
| } |
| } catch (SystemException se) { |
| throw se; |
| } catch (Exception e) { |
| throw new SystemException(ErrorCode.SYSE0001, e); |
| } |
| throw new SystemException(ErrorCode.XPTY0004); |
| } |
| |
| public static int getBaseTypeForArithmetics(int tid) throws SystemException { |
| if (tid >= BuiltinTypeConstants.BUILTIN_TYPE_COUNT) { |
| throw new SystemException(ErrorCode.XPTY0004); |
| } |
| while (true) { |
| switch (tid) { |
| case ValueTag.XS_STRING_TAG: |
| case ValueTag.XS_DECIMAL_TAG: |
| case ValueTag.XS_INTEGER_TAG: |
| case ValueTag.XS_FLOAT_TAG: |
| case ValueTag.XS_DOUBLE_TAG: |
| case ValueTag.XS_ANY_URI_TAG: |
| case ValueTag.XS_BOOLEAN_TAG: |
| case ValueTag.XS_DATE_TAG: |
| case ValueTag.XS_DATETIME_TAG: |
| case ValueTag.XS_TIME_TAG: |
| case ValueTag.XS_DAY_TIME_DURATION_TAG: |
| case ValueTag.XS_YEAR_MONTH_DURATION_TAG: |
| case ValueTag.XS_BASE64_BINARY_TAG: |
| case ValueTag.XS_HEX_BINARY_TAG: |
| case ValueTag.XS_QNAME_TAG: |
| case ValueTag.XS_G_DAY_TAG: |
| case ValueTag.XS_G_MONTH_DAY_TAG: |
| case ValueTag.XS_G_MONTH_TAG: |
| case ValueTag.XS_G_YEAR_MONTH_TAG: |
| case ValueTag.XS_G_YEAR_TAG: |
| case ValueTag.XS_UNTYPED_ATOMIC_TAG: |
| return tid; |
| |
| case ValueTag.XS_LONG_TAG: |
| case ValueTag.XS_NEGATIVE_INTEGER_TAG: |
| case ValueTag.XS_NON_POSITIVE_INTEGER_TAG: |
| case ValueTag.XS_NON_NEGATIVE_INTEGER_TAG: |
| case ValueTag.XS_POSITIVE_INTEGER_TAG: |
| case ValueTag.XS_UNSIGNED_INT_TAG: |
| case ValueTag.XS_UNSIGNED_LONG_TAG: |
| case ValueTag.XS_INT_TAG: |
| case ValueTag.XS_UNSIGNED_SHORT_TAG: |
| case ValueTag.XS_SHORT_TAG: |
| case ValueTag.XS_UNSIGNED_BYTE_TAG: |
| case ValueTag.XS_BYTE_TAG: |
| return ValueTag.XS_INTEGER_TAG; |
| |
| case ValueTag.XS_ANY_ATOMIC_TAG: |
| throw new SystemException(ErrorCode.XPTY0004); |
| |
| default: |
| tid = BuiltinTypeRegistry.INSTANCE.getSchemaTypeById(tid).getBaseType().getTypeId(); |
| return tid; |
| } |
| } |
| } |
| |
| } |