Package org.exist.xquery.value

Source Code of org.exist.xquery.value.OrderedDurationValue

package org.exist.xquery.value;

import java.math.BigDecimal;
import java.text.Collator;

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;

import org.exist.xquery.Constants;
import org.exist.xquery.ErrorCodes;
import org.exist.xquery.XPathException;

/**
* @author <a href="mailto:piotr@ideanest.com">Piotr Kaminski</a>
*/
abstract class OrderedDurationValue extends DurationValue {

  OrderedDurationValue(Duration duration) throws XPathException {
    super(duration);
  }

  public boolean compareTo(Collator collator, int operator, AtomicValue other) throws XPathException {
    if (other.isEmpty())
      {return false;}
    final int r = compareTo(collator, other)
    if (operator != Constants.EQ && operator != Constants.NEQ){
      if (getType() == Type.DURATION)
        {throw new XPathException(ErrorCodes.XPTY0004,
            "cannot compare unordered " + Type.getTypeName(getType()) + " to "
            + Type.getTypeName(other.getType()));}
      if (other.getType()== Type.DURATION)
        {throw new XPathException(ErrorCodes.XPTY0004,
          "cannot compare " + Type.getTypeName(getType()) + " to unordered "
          + Type.getTypeName(other.getType()));}
      if (Type.getCommonSuperType(getType(), other.getType()) == Type.DURATION)
        {throw new XPathException(ErrorCodes.XPTY0004,
          "cannot compare " + Type.getTypeName(getType()) + " to "
          + Type.getTypeName(other.getType()));}
    }
    switch (operator) {
      case Constants.EQ :
        return r == DatatypeConstants.EQUAL;
      case Constants.NEQ :
        return r != DatatypeConstants.EQUAL;
      case Constants.LT :
        return r == DatatypeConstants.LESSER;
      case Constants.LTEQ :
        return r == DatatypeConstants.LESSER || r == DatatypeConstants.EQUAL;
      case Constants.GT :
        return r == DatatypeConstants.GREATER;
      case Constants.GTEQ :
        return r == DatatypeConstants.GREATER || r == DatatypeConstants.EQUAL;
      default :
        throw new XPathException("Unknown operator type in comparison");
    }
  }

  public int compareTo(Collator collator, AtomicValue other) throws XPathException {
    if (other.isEmpty())
      {return Constants.INFERIOR;}
    if (Type.subTypeOf(other.getType(), Type.DURATION)) {
      //Take care : this method doesn't seem to take ms into account
      final int r = duration.compare(((DurationValue) other).duration);
      //compare fractional seconds to work around the JDK standard behaviour
      if (r == DatatypeConstants.EQUAL &&
          ((BigDecimal)duration.getField(DatatypeConstants.SECONDS)) != null &&
          ((BigDecimal)(((DurationValue) other).duration).getField(DatatypeConstants.SECONDS)) != null) {
        if (((BigDecimal)duration.getField(DatatypeConstants.SECONDS)).compareTo(
            ((BigDecimal)(((DurationValue) other).duration).getField(DatatypeConstants.SECONDS))) == DatatypeConstants.EQUAL)
            {return Constants.EQUAL;}
        return (((BigDecimal)duration.getField(DatatypeConstants.SECONDS)).compareTo(
            ((BigDecimal)(((DurationValue) other).duration).getField(DatatypeConstants.SECONDS)))) == DatatypeConstants.LESSER ?
            Constants.INFERIOR : Constants.SUPERIOR;
      }
      if (r == DatatypeConstants.INDETERMINATE) {throw new RuntimeException("indeterminate order between totally ordered duration values " + this + " and " + other);}
      return r;   
    }
    throw new XPathException(
        "Type error: cannot compare " + Type.getTypeName(getType()) + " to "
        + Type.getTypeName(other.getType()));
  }

  public AtomicValue max(Collator collator, AtomicValue other) throws XPathException {
    if (other.getType() != getType()) {throw new XPathException("cannot obtain maximum across different non-numeric data types");}
    return compareTo(null, other) > 0 ? this : other;
  }

  public AtomicValue min(Collator collator, AtomicValue other) throws XPathException {
    if (other.getType() != getType()) {throw new XPathException("cannot obtain minimum across different non-numeric data types");}
    return compareTo(null, other) < 0 ? this : other;
  }

  public ComputableValue plus(ComputableValue other) throws XPathException {
    switch(other.getType()) {
      case Type.DAY_TIME_DURATION: {
        //if (getType() != other.getType()) throw new IllegalArgumentException();  // not a match after all
        final Duration a = getCanonicalDuration();
        final Duration b = ((OrderedDurationValue) other).getCanonicalDuration()
        final Duration result = createSameKind(a.add(b)).getCanonicalDuration();
        //TODO : move instantiation to the right place
        return new DayTimeDurationValue(result); }     
      case Type.YEAR_MONTH_DURATION: {
        //if (getType() != other.getType()) throw new IllegalArgumentException();  // not a match after all
        final Duration a = getCanonicalDuration();
        final Duration b = ((OrderedDurationValue) other).getCanonicalDuration()
        final Duration result = createSameKind(a.add(b)).getCanonicalDuration();
        //TODO : move instantiation to the right place
        return new YearMonthDurationValue(result); }
      case Type.DURATION: {
        //if (getType() != other.getType()) throw new IllegalArgumentException();  // not a match after all
        final Duration a = getCanonicalDuration();
        final Duration b = ((DurationValue) other).getCanonicalDuration()
        final Duration result = createSameKind(a.add(b)).getCanonicalDuration();
        //TODO : move instantiation to the right place
        return new DurationValue(result); }
      case Type.TIME:
      case Type.DATE_TIME:
      case Type.DATE:
        final AbstractDateTimeValue date = (AbstractDateTimeValue) other;
        final XMLGregorianCalendar gc = (XMLGregorianCalendar) date.calendar.clone();
        gc.add(duration);
        //Shift one year
        if (gc.getYear() <0)
          {gc.setYear(gc.getYear() - 1);}
        return date.createSameKind(gc);
      default:
        throw new XPathException(ErrorCodes.XPTY0004, "cannot add " +
            Type.getTypeName(other.getType()) + "('" + other.getStringValue() + "') from " +
            Type.getTypeName(getType()) + "('" + getStringValue() + "')");    }
  }

  public ComputableValue minus(ComputableValue other) throws XPathException {
    switch(other.getType()) {
    case Type.DAY_TIME_DURATION: {
      if (getType() != other.getType())
        {throw new XPathException(ErrorCodes.XPTY0004, "Tried to substract " +
            Type.getTypeName(other.getType()) + "('" + other.getStringValue() + "') from " +
            Type.getTypeName(getType()) + "('" + getStringValue() + "')");}
      final Duration a = getCanonicalDuration();
      final Duration b = ((OrderedDurationValue) other).getCanonicalDuration()
      final Duration result = createSameKind(a.subtract(b)).getCanonicalDuration();
      return new DayTimeDurationValue(result); }       
    case Type.YEAR_MONTH_DURATION: {
      if (getType() != other.getType())
        {throw new XPathException(ErrorCodes.XPTY0004, "Tried to substract " +
            Type.getTypeName(other.getType()) + "('" + other.getStringValue() + "') from " +
            Type.getTypeName(getType()) + "('" + getStringValue() + "')");}
      final Duration a = getCanonicalDuration();
      final Duration b = ((OrderedDurationValue) other).getCanonicalDuration()
      final Duration result = createSameKind(a.subtract(b)).getCanonicalDuration();
      return new YearMonthDurationValue(result); }
    /*
    case Type.TIME:
    case Type.DATE_TIME:
    case Type.DATE:
      AbstractDateTimeValue date = (AbstractDateTimeValue) other;
      XMLGregorianCalendar gc = (XMLGregorianCalendar) date.calendar.clone();
      gc.substract(duration);
      return date.createSameKind(gc);
    */
    default:
      throw new XPathException("err:XPTY0004: cannot substract " +
          Type.getTypeName(other.getType()) + "('" + other.getStringValue() + "') from " +
          Type.getTypeName(getType()) + "('" + getStringValue() + "')");
    }
    /*
    if(other.getType() == getType()) {
      return createSameKind(duration.subtract(((OrderedDurationValue)other).duration));
    }
    throw new XPathException("Operand to minus should be of type " + Type.getTypeName(getType()) + "; got: " +
      Type.getTypeName(other.getType()));
    */
  }
 
  /**
   * Convert the given value to a big decimal if it's a number, keeping as much precision
   * as possible.
   *
   * @param x a value to convert to a big decimal
   * @param exceptionMessagePrefix the beginning of the message to throw in an exception, will be suffixed with the type of the value given
   * @return the big decimal equivalent of the value
   * @throws XPathException if the value is not of a numeric type
   */
  protected BigDecimal numberToBigDecimal(ComputableValue x, String exceptionMessagePrefix) throws XPathException {
    if (!Type.subTypeOf(x.getType(), Type.NUMBER)) {
                    throw new XPathException(exceptionMessagePrefix + Type.getTypeName(x.getType()));
   
    if (((NumericValue) x).isInfinite() || ((NumericValue) x).isNaN()) {
                    throw new XPathException(ErrorCodes.XPTY0004, "Tried to convert '" + (NumericValue) x + "' to BigDecimal")
                }
               
    if (x.conversionPreference(BigDecimal.class) < Integer.MAX_VALUE) {
                    return x.toJavaObject(BigDecimal.class);
                } else {
                    return new BigDecimal(((NumericValue) x).getDouble());   
                }
  }
}
TOP

Related Classes of org.exist.xquery.value.OrderedDurationValue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.