#include "../../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include "ATGMonthDayOrDerivedImpl.hpp" #include #include "../../exceptions/XPath2TypeCastException.hpp" #include #include #include #include #include // defines X() and XMLCh* #include #include #include #include "../../utils/DateUtils.hpp" #include #include #include ATGMonthDayOrDerivedImpl:: ATGMonthDayOrDerivedImpl(const XMLCh* typeURI, const XMLCh* typeName, const XMLCh* value, XPath2MemoryManager* memMgr, const DynamicContext* context): ATGMonthDayOrDerived(memMgr), _typeName(typeName), _typeURI(typeURI) { setGMonthDay(value, context); } /* Get the name of the primitive type (basic type) of this type * (ie "decimal" for xs:decimal) */ const XMLCh* ATGMonthDayOrDerivedImpl::getPrimitiveTypeName() const { return this->getPrimitiveName(); } const XMLCh* ATGMonthDayOrDerivedImpl::getPrimitiveName() { return XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_MONTHDAY; } /* Get the name of this type (ie "integer" for xs:integer) */ const XMLCh* ATGMonthDayOrDerivedImpl::getTypeName() const { return _typeName; } /* Get the namespace URI for this type */ const XMLCh* ATGMonthDayOrDerivedImpl::getTypeURI() const { return _typeURI; } AnyAtomicType::AtomicObjectType ATGMonthDayOrDerivedImpl::getTypeIndex() { return AnyAtomicType::G_MONTH_DAY; } /* returns the XMLCh* (canonical) representation of this type */ const XMLCh* ATGMonthDayOrDerivedImpl::asString(const DynamicContext* context) const { XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer buffer(1023, context->getMemoryManager()); buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(_MM->asString(2, context)); buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(_DD->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 ATGMonthDayOrDerivedImpl::equals(const AnyAtomicType* target, const DynamicContext* context) const { if(this->getPrimitiveTypeIndex() != target->getPrimitiveTypeIndex()) { DSLthrow(IllegalArgumentException,X("ATGMonthDayOrDerivedImpl::equals"), X("Equality operator for given types not supported")); } ATGMonthDayOrDerivedImpl* targetGMonthDay = (ATGMonthDayOrDerivedImpl*)target; if ( _hasTimezone == targetGMonthDay->_hasTimezone) { return ( (!_hasTimezone || _timezone->equals(targetGMonthDay->_timezone)) && this->_MM->equals(targetGMonthDay->_MM, context) && this->_DD->equals(targetGMonthDay->_DD, context) ); } else { return false; } } /** Returns true if this is greater than other. Ignores timezones. * Returns false otherwise. */ bool ATGMonthDayOrDerivedImpl::greaterThan(const ATGMonthDayOrDerived* other, const DynamicContext* context) const { const ATGMonthDayOrDerivedImpl* thisImpl = this; const ATGMonthDayOrDerivedImpl* otherImpl = (const ATGMonthDayOrDerivedImpl*)other; if (!thisImpl->hasTimezone()) thisImpl = (const ATGMonthDayOrDerivedImpl*)thisImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); if (!otherImpl->hasTimezone()) otherImpl = (const ATGMonthDayOrDerivedImpl*)otherImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); return (thisImpl->_MM->greaterThan(otherImpl->_MM, context) || (thisImpl->_MM->equals(otherImpl->_MM, context) && thisImpl->_DD->greaterThan(otherImpl->_DD, context)) || (thisImpl->_MM->equals(otherImpl->_MM, context) && thisImpl->_DD->equals(otherImpl->_DD, context) && thisImpl->_timezone->greaterThan(otherImpl->_timezone))); } /** Returns true if this is less than other. Ignores timezones. * Returns false otherwise. */ bool ATGMonthDayOrDerivedImpl::lessThan(const ATGMonthDayOrDerived* other, const DynamicContext* context) const { const ATGMonthDayOrDerivedImpl* thisImpl = this; const ATGMonthDayOrDerivedImpl* otherImpl = (const ATGMonthDayOrDerivedImpl*)other; if (!thisImpl->hasTimezone()) thisImpl = (const ATGMonthDayOrDerivedImpl*)thisImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); if (!otherImpl->hasTimezone()) otherImpl = (const ATGMonthDayOrDerivedImpl*)otherImpl->setTimezone(new (context->getMemoryManager()) Timezone(context->getImplicitTimezone(), context), context); return (thisImpl->_MM->lessThan(otherImpl->_MM, context) || (thisImpl->_MM->equals(otherImpl->_MM, context) && thisImpl->_DD->lessThan(otherImpl->_DD, context)) || (thisImpl->_MM->equals(otherImpl->_MM, context) && thisImpl->_DD->equals(otherImpl->_DD, context) && thisImpl->_timezone->lessThan(otherImpl->_timezone))); } /** Returns true if a timezone is defined for this. False otherwise.*/ bool ATGMonthDayOrDerivedImpl::hasTimezone() const { return _hasTimezone; } /** Sets the timezone to the given timezone.*/ const ATGMonthDayOrDerived* ATGMonthDayOrDerivedImpl::setTimezone(const Timezone* timezone, const DynamicContext* context) const { bool hasTimezone = timezone == 0 ? false : true; XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer buffer(1023, context->getMemoryManager()); buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(_MM->asString(2, context)); buffer.append(XERCES_CPP_NAMESPACE_QUALIFIER chDash); buffer.append(_DD->asString(2, context)); if (hasTimezone) buffer.append(timezone->asString(context)); const XMLCh* gMonthDay = context->getMemoryManager()->getPooledString(buffer.getRawBuffer()); return DatatypeFactory::STR2AT::createGMonthDayOrDerived(context->getMemoryManager(), this->getTypeURI(), this->getTypeName(), gMonthDay, context); } AnyAtomicType::AtomicObjectType ATGMonthDayOrDerivedImpl::getPrimitiveTypeIndex() const { return this->getTypeIndex(); } /** Releases the memory used by this Item */ void ATGMonthDayOrDerivedImpl::release() const { //TODO needs to check for ownership before releasing! getMemoryManager()->deallocate((void*)this); } /* parse the gMonthDay */ void ATGMonthDayOrDerivedImpl::setGMonthDay(const XMLCh* const value, const DynamicContext* context) { unsigned int length = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(value); if(value == NULL) { DSLthrow(XPath2TypeCastException,X("XSGMonthDayImpl::setGMonthDay"), X("Invalid representation of gMonthDay")); } // State variables etc. bool gotDigit = false; unsigned int pos = 0; long int tmpnum = 0; unsigned int numDigit = 0; // defaulting values MAPM MM = 0; MAPM DD = 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; // format : --MM-DD([+/-]hh:mm) bool wrongformat = false; if ( length < 7 || value[0] != L'-' || value[1] != L'-' || value[4] != L'-') { wrongformat = true; }else { pos = 2; } 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: { tmpnum *= 10; tmpnum += static_cast(tmpChar - 0x0030); gotDigit = true; numDigit ++; break; } case L'-' : { if ( gotDigit ) { if (state == 0 && numDigit == 2 ) { MM = tmpnum; tmpnum = 0; gotDigit = false; pos = 5; numDigit = 0; } else if (state == 1 && numDigit == 2) { DD = tmpnum; state = 5; gotDigit = false; _hasTimezone = true; zonepos = false; tmpnum = 0; numDigit = 0; } else { wrongformat = true; } state ++; } else { wrongformat = true; } break; } case L'+' : { if ( gotDigit && state == 1 && numDigit == 2 ) { DD = 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 ) { DD = tmpnum; state = 8; // final state _hasTimezone = true; gotDigit = false; tmpnum = 0; numDigit = 0; } else { wrongformat = true; } break; } default: wrongformat = true; } } if (gotDigit) { if ( gotDigit && state == 7 && numDigit == 2) { zonemm = tmpnum; }else if ( gotDigit && state == 1 && numDigit == 2) { DD = tmpnum; }else { wrongformat = true; } } // check time format if ( MM > 12 || DD > 31 || zonehh > 24 || zonemm > 60 ) { wrongformat = true; } if (wrongformat) { DSLthrow(XPath2TypeCastException,X("XSGMonthDayImpl::setGMonthDay"), X("Invalid representation of gMonthDay")); } // 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); _DD = DatatypeFactory::POD2AT::createNonNegativeInteger(context->getMemoryManager(), DD, context); }