#include "../../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include "ATGYearMonthOrDerivedImpl.hpp" #include #include "../../exceptions/XPath2TypeCastException.hpp" #include #include #include #include #include // defines X() and XMLCh* #include #include #include #include #include "../../utils/DateUtils.hpp" #include #include ATGYearMonthOrDerivedImpl:: ATGYearMonthOrDerivedImpl(const XMLCh* typeURI, const XMLCh* typeName, const XMLCh* value, XPath2MemoryManager* memMgr, const DynamicContext* context): ATGYearMonthOrDerived(memMgr), _typeName(typeName), _typeURI(typeURI) { setGYearMonth(value, context); } /* Get the name of the primitive type (basic type) of this type * (ie "decimal" for xs:decimal) */ const XMLCh* ATGYearMonthOrDerivedImpl::getPrimitiveTypeName() const { return getPrimitiveName(); } const XMLCh* ATGYearMonthOrDerivedImpl::getPrimitiveName() { return XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_YEARMONTH; } /* Get the name of this type (ie "integer" for xs:integer) */ const XMLCh* ATGYearMonthOrDerivedImpl::getTypeName() const { return _typeName; } /* Get the namespace URI for this type */ const XMLCh* ATGYearMonthOrDerivedImpl::getTypeURI() const { return _typeURI; } AnyAtomicType::AtomicObjectType ATGYearMonthOrDerivedImpl::getTypeIndex() { return AnyAtomicType::G_YEAR_MONTH; } /* returns the XMLCh* (canonical) representation of this type */ const XMLCh* ATGYearMonthOrDerivedImpl::asString(const DynamicContext* context) const { XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer buffer(1023, context->getMemoryManager()); if(_YY->greaterThan(DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), 9999, context), context) || _YY->lessThan(DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), -9999, context), context)) { buffer.set(_YY->asString(context)); } else { buffer.set(_YY->asString(4, context)); //pad to 4 digits } buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(_MM->asString(2, context)); if ( _hasTimezone == true ) { buffer.append(_timezone->asString(context)); } return context->getMemoryManager()->getPooledString(buffer.getRawBuffer()); } /* returns true if the two objects * false otherwise */ bool ATGYearMonthOrDerivedImpl::equals(const AnyAtomicType* target, const DynamicContext* context) const { if(this->getPrimitiveTypeIndex() != target->getPrimitiveTypeIndex()) { DSLthrow(IllegalArgumentException,X("ATGYearMonthOrDerivedImpl::equals"), X("Equality operator for given types not supported")); } ATGYearMonthOrDerivedImpl* targetGYearMonth = (ATGYearMonthOrDerivedImpl*)target; if ( _hasTimezone == targetGYearMonth->_hasTimezone) { return ( (!_hasTimezone || _timezone->equals(targetGYearMonth->_timezone)) && this->_YY->equals(targetGYearMonth->_YY, context) && this->_MM->equals(targetGYearMonth->_MM, context) ); } else { return false; } } /** Returns true if this is greater than other. Ignores timezones. * Returns false otherwise. */ bool ATGYearMonthOrDerivedImpl::greaterThan(const ATGYearMonthOrDerived* other, const DynamicContext* context) const { const ATGYearMonthOrDerivedImpl* thisImpl = this; const ATGYearMonthOrDerivedImpl* otherImpl = (const ATGYearMonthOrDerivedImpl*)other; if (!thisImpl->hasTimezone()) thisImpl = (const ATGYearMonthOrDerivedImpl*)thisImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); if (!otherImpl->hasTimezone()) otherImpl = (const ATGYearMonthOrDerivedImpl*)otherImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); return (thisImpl->_YY->greaterThan(otherImpl->_YY, context) || (thisImpl->_YY->equals(otherImpl->_YY, context) && thisImpl->_MM->greaterThan(otherImpl->_MM, context)) || (thisImpl->_YY->equals(otherImpl->_YY, context) && thisImpl->_MM->equals(otherImpl->_MM, context) && thisImpl->_timezone->greaterThan(otherImpl->_timezone))); } /** Returns true if this is less than other. Ignores timezones. * Returns false otherwise. */ bool ATGYearMonthOrDerivedImpl::lessThan(const ATGYearMonthOrDerived* other, const DynamicContext* context) const { const ATGYearMonthOrDerivedImpl* thisImpl = this; const ATGYearMonthOrDerivedImpl* otherImpl = (const ATGYearMonthOrDerivedImpl*)other; if (!thisImpl->hasTimezone()) thisImpl = (const ATGYearMonthOrDerivedImpl*)thisImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); if (!otherImpl->hasTimezone()) otherImpl = (const ATGYearMonthOrDerivedImpl*)otherImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); return (thisImpl->_YY->lessThan(otherImpl->_YY, context) || (thisImpl->_YY->equals(otherImpl->_YY, context) && thisImpl->_MM->lessThan(otherImpl->_MM, context)) || (thisImpl->_YY->equals(otherImpl->_YY, context) && thisImpl->_MM->equals(otherImpl->_MM, context) && thisImpl->_timezone->lessThan(otherImpl->_timezone))); } /** Returns true if a timezone is defined for this. False otherwise.*/ bool ATGYearMonthOrDerivedImpl::hasTimezone() const { return _hasTimezone; } /** Sets the timezone to the given timezone.*/ const ATGYearMonthOrDerived* ATGYearMonthOrDerivedImpl::setTimezone(const Timezone* timezone, const DynamicContext* context) const { bool hasTimezone = timezone == 0 ? false : true; XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer buffer(1023, context->getMemoryManager()); if(_YY->greaterThan(DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), 9999, context), context)) { buffer.set(_YY->asString(context)); } else { buffer.set(_YY->asString(4, context)); //pad to 4 digits } buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(_MM->asString(2, context)); if (hasTimezone) buffer.append(timezone->asString(context)); const XMLCh* gYearMonth = context->getMemoryManager()->getPooledString(buffer.getRawBuffer()); return DatatypeFactory::STR2AT::createGYearMonthOrDerived(context->getMemoryManager(), this->getTypeURI(), this->getTypeName(), gYearMonth, context); } AnyAtomicType::AtomicObjectType ATGYearMonthOrDerivedImpl::getPrimitiveTypeIndex() const { return this->getTypeIndex(); } /** Releases the memory used by this Item */ void ATGYearMonthOrDerivedImpl::release() const { //TODO needs to check for ownership before releasing! getMemoryManager()->deallocate((void*)this); } /* parse the gYearMonth */ void ATGYearMonthOrDerivedImpl::setGYearMonth(const XMLCh* const value, const DynamicContext* context) { unsigned int length = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(value); if(value == NULL) { DSLthrow(XPath2TypeCastException,X("ATGYearMonthOrDerivedImpl::setGYearMonth"), X("Invalid representation of gYearMonth")); } // State variables etc. bool gotDigit = false; unsigned int pos = 0; long int tmpnum = 0; unsigned int numDigit = 0; bool negative = false; // defaulting values MAPM YY = 0; MAPM MM = 0; _hasTimezone = false; bool zonepos = false; int zonehh = 0; int zonemm = 0; int state = 0 ; // 0 = year / 1 = month / 2 = day / 3 = hour // 4 = minutes / 5 = sec / 6 = timezonehour / 7 = timezonemin XMLCh tmpChar; bool wrongformat = false; if ( length > 0 && value[0] == L'-' ) { negative = true; pos = 1; }else{ pos = 0; } while ( ! wrongformat && pos < length) { tmpChar = value[pos]; pos++; switch(tmpChar) { case 0x0030: case 0x0031: case 0x0032: case 0x0033: case 0x0034: case 0x0035: case 0x0036: case 0x0037: case 0x0038: case 0x0039: { numDigit ++; tmpnum *= 10; tmpnum += static_cast(tmpChar - 0x0030); gotDigit = true; break; } case L'-' : { if ( gotDigit ) { if (state == 0 && numDigit >= 4) { YY = tmpnum; tmpnum = 0; gotDigit = false; numDigit = 0; } else if (state == 1 && numDigit == 2) { MM = tmpnum; tmpnum = 0; gotDigit = false; _hasTimezone = true; zonepos = false; state = 5; numDigit = 0; } else { wrongformat = true; } state ++; } else { wrongformat = true; } break; } case L'+' : { if ( gotDigit && state == 1 && numDigit == 2) { MM = tmpnum; state = 6; gotDigit = false; _hasTimezone = true; zonepos = true; tmpnum = 0; numDigit = 0; } else { wrongformat = true; } break; } case L':' : { if (gotDigit && state == 6 && numDigit == 2) { zonehh = tmpnum; tmpnum = 0; gotDigit = false; state ++; numDigit = 0; }else { wrongformat = true; } break; } case L'Z' : { if (gotDigit && state == 1 && numDigit == 2) { MM = tmpnum; state = 8; // final state _hasTimezone = true; gotDigit = false; tmpnum = 0; numDigit = 0; } else { wrongformat = true; } break; } default: wrongformat = true; } } if (negative) { YY = YY * -1; } if (gotDigit) { if ( gotDigit && state == 7 && numDigit == 2) { zonemm = tmpnum; } else if ( gotDigit && state == 1 && numDigit == 2) { MM = tmpnum; } else { wrongformat = true; } } // check time format if ( MM > 12 || zonehh > 24 || zonemm > 60 || YY == 0 ) { wrongformat = true; } if ( wrongformat) { DSLthrow(XPath2TypeCastException,X("ATGYearMonthOrDerivedImpl::setGYearMonth"), X("Invalid representation of gYearMonth")); } // Create Timezone object, clean this up in future if (zonepos == false) { zonehh *= -1; zonemm *= -1; } _timezone = new Timezone(zonehh, zonemm); _MM = DatatypeFactory::POD2AT::createNonNegativeInteger(context->getMemoryManager(), MM, context); _YY = DatatypeFactory::POD2AT::createInteger(context->getMemoryManager(), YY, context); }