blob: 78f46cdc05a7ca9dc406aaa28f1ebea4076aef17 [file] [log] [blame]
/**************************************************************
*
* 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.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include "SchemaRestrictionContext.hxx"
#include "xformsapi.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmlnmspe.hxx>
#include <xmloff/xmltkmap.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmlimp.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/Type.hxx>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Time.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/xforms/XDataTypeRepository.hpp>
#include <com/sun/star/xsd/DataTypeClass.hpp>
#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
#include <tools/debug.hxx>
using rtl::OUString;
using com::sun::star::uno::Reference;
using com::sun::star::uno::Exception;
using com::sun::star::uno::Any;
using com::sun::star::uno::makeAny;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::util::Date;
using com::sun::star::util::DateTime;
using com::sun::star::xml::sax::XAttributeList;
using com::sun::star::beans::XPropertySet;
using com::sun::star::beans::XPropertySetInfo;
using com::sun::star::xforms::XDataTypeRepository;
using namespace xmloff::token;
static SvXMLTokenMapEntry aAttributes[] =
{
TOKEN_MAP_ENTRY( NONE, BASE ),
XML_TOKEN_MAP_END
};
static SvXMLTokenMapEntry aChildren[] =
{
TOKEN_MAP_ENTRY( XSD, LENGTH ),
TOKEN_MAP_ENTRY( XSD, MINLENGTH ),
TOKEN_MAP_ENTRY( XSD, MAXLENGTH ),
TOKEN_MAP_ENTRY( XSD, MININCLUSIVE ),
TOKEN_MAP_ENTRY( XSD, MINEXCLUSIVE ),
TOKEN_MAP_ENTRY( XSD, MAXINCLUSIVE ),
TOKEN_MAP_ENTRY( XSD, MAXEXCLUSIVE ),
TOKEN_MAP_ENTRY( XSD, PATTERN ),
// ??? XML_ENUMERATION
TOKEN_MAP_ENTRY( XSD, WHITESPACE ),
TOKEN_MAP_ENTRY( XSD, TOTALDIGITS ),
TOKEN_MAP_ENTRY( XSD, FRACTIONDIGITS ),
XML_TOKEN_MAP_END
};
SchemaRestrictionContext::SchemaRestrictionContext(
SvXMLImport& rImport,
sal_uInt16 nPrefix,
const OUString& rLocalName,
Reference<com::sun::star::xforms::XDataTypeRepository>& rRepository,
const OUString& sTypeName ) :
TokenContext( rImport, nPrefix, rLocalName, aAttributes, aChildren ),
mxRepository( rRepository ),
msTypeName( sTypeName ),
msBaseName()
{
DBG_ASSERT( mxRepository.is(), "need repository" );
}
SchemaRestrictionContext::~SchemaRestrictionContext()
{
}
void SchemaRestrictionContext::CreateDataType()
{
// only do something if we don't have a data type already
if( mxDataType.is() )
return;
DBG_ASSERT( msBaseName.getLength() > 0, "no base name?" );
DBG_ASSERT( mxRepository.is(), "no repository?" );
try
{
mxDataType =
Reference<XPropertySet>(
mxRepository->cloneDataType(
lcl_getBasicTypeName( mxRepository,
GetImport().GetNamespaceMap(),
msBaseName ),
msTypeName ),
UNO_QUERY );
}
catch( const Exception& )
{
DBG_ERROR( "exception during type creation" );
}
DBG_ASSERT( mxDataType.is(), "can't create type" );
}
void SchemaRestrictionContext::HandleAttribute(
sal_uInt16 nToken,
const OUString& rValue )
{
if( nToken == XML_BASE )
{
msBaseName = rValue;
}
}
typedef Any (*convert_t)( const OUString& );
Any lcl_string( const OUString& rValue )
{
return makeAny( rValue );
}
Any lcl_int32( const OUString& rValue )
{
sal_Int32 nValue;
bool bSuccess = SvXMLUnitConverter::convertNumber( nValue, rValue );
return bSuccess ? makeAny( nValue ) : Any();
}
Any lcl_int16( const OUString& rValue )
{
sal_Int32 nValue;
bool bSuccess = SvXMLUnitConverter::convertNumber( nValue, rValue );
return bSuccess ? makeAny( static_cast<sal_Int16>( nValue ) ) : Any();
}
Any lcl_whitespace( const OUString& rValue )
{
Any aValue;
if( IsXMLToken( rValue, XML_PRESERVE ) )
aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Preserve;
else if( IsXMLToken( rValue, XML_REPLACE ) )
aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Replace;
else if( IsXMLToken( rValue, XML_COLLAPSE ) )
aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Collapse;
return aValue;
}
Any lcl_double( const OUString& rValue )
{
double fValue;
bool bSuccess = SvXMLUnitConverter::convertDouble( fValue, rValue );
return bSuccess ? makeAny( fValue ) : Any();
}
Any lcl_date( const OUString& rValue )
{
Any aAny;
// parse ISO date
sal_Int32 nPos1 = rValue.indexOf( sal_Unicode('-') );
sal_Int32 nPos2 = rValue.indexOf( sal_Unicode('-'), nPos1 + 1 );
if( nPos1 > 0 && nPos2 > 0 )
{
Date aDate;
aDate.Year = static_cast<sal_uInt16>(
rValue.copy( 0, nPos1 ).toInt32() );
aDate.Month = static_cast<sal_uInt16>(
rValue.copy( nPos1 + 1, nPos2 - nPos1 - 1 ).toInt32() );
aDate.Day = static_cast<sal_uInt16>(
rValue.copy( nPos2 + 1 ).toInt32() );
aAny <<= aDate;
}
return aAny;
}
Any lcl_dateTime( const OUString& rValue )
{
DateTime aDateTime;
bool bSuccess = SvXMLUnitConverter::convertDateTime( aDateTime, rValue );
return bSuccess ? makeAny( aDateTime ) : Any();
}
Any lcl_time( const OUString& rValue )
{
Any aAny;
DateTime aDateTime;
if( SvXMLUnitConverter::convertTime( aDateTime, rValue ) )
{
com::sun::star::util::Time aTime;
aTime.Hours = aDateTime.Hours;
aTime.Minutes = aDateTime.Minutes;
aTime.Seconds = aDateTime.Seconds;
aTime.HundredthSeconds = aDateTime.HundredthSeconds;
aAny <<= aTime;
}
return aAny;
}
SvXMLImportContext* SchemaRestrictionContext::HandleChild(
sal_uInt16 nToken,
sal_uInt16 nPrefix,
const OUString& rLocalName,
const Reference<XAttributeList>& xAttrList )
{
// find value
OUString sValue;
sal_Int16 nLength = xAttrList->getLength();
for( sal_Int16 n = 0; n < nLength; n++ )
{
if( IsXMLToken( xAttrList->getNameByIndex( n ), XML_VALUE ) )
sValue = xAttrList->getValueByIndex( n );
}
// determine property name + suitable converter
OUString sPropertyName;
convert_t pConvert = NULL;
switch( nToken )
{
case XML_LENGTH:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Length"));
pConvert = &lcl_int32;
break;
case XML_MINLENGTH:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinLength"));
pConvert = &lcl_int32;
break;
case XML_MAXLENGTH:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxLength"));
pConvert = &lcl_int32;
break;
case XML_TOTALDIGITS:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("TotalDigits"));
pConvert = &lcl_int32;
break;
case XML_FRACTIONDIGITS:
sPropertyName =OUString(RTL_CONSTASCII_USTRINGPARAM("FractionDigits"));
pConvert = &lcl_int32;
break;
case XML_PATTERN:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Pattern"));
pConvert = &lcl_string;
break;
case XML_WHITESPACE:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("WhiteSpace"));
pConvert = &lcl_whitespace;
break;
case XML_MININCLUSIVE:
case XML_MINEXCLUSIVE:
case XML_MAXINCLUSIVE:
case XML_MAXEXCLUSIVE:
{
// these attributes are mapped to different properties.
// To determine the property name, we use an attribute
// dependent prefix and a type dependent suffix. The
// converter is only type dependent.
// first, attribute-dependent prefix
switch( nToken )
{
case XML_MININCLUSIVE:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinInclusive"));
break;
case XML_MINEXCLUSIVE:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinExclusive"));
break;
case XML_MAXINCLUSIVE:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxInclusive"));
break;
case XML_MAXEXCLUSIVE:
sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxExclusive"));
break;
}
// second, type-dependent suffix + converter
switch( lcl_getTypeClass( mxRepository,
GetImport().GetNamespaceMap(),
msBaseName ) )
{
case com::sun::star::xsd::DataTypeClass::DECIMAL:
case com::sun::star::xsd::DataTypeClass::DOUBLE:
case com::sun::star::xsd::DataTypeClass::FLOAT:
sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Double"));
pConvert = &lcl_double;
break;
case com::sun::star::xsd::DataTypeClass::DATETIME:
sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("DateTime"));
pConvert = &lcl_dateTime;
break;
case com::sun::star::xsd::DataTypeClass::DATE:
sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Date"));
pConvert = &lcl_date;
break;
case com::sun::star::xsd::DataTypeClass::TIME:
sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Time"));
pConvert = &lcl_time;
break;
case com::sun::star::xsd::DataTypeClass::gYear:
case com::sun::star::xsd::DataTypeClass::gDay:
case com::sun::star::xsd::DataTypeClass::gMonth:
sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Int"));
pConvert = &lcl_int16;
break;
case com::sun::star::xsd::DataTypeClass::STRING:
case com::sun::star::xsd::DataTypeClass::anyURI:
case com::sun::star::xsd::DataTypeClass::BOOLEAN:
// invalid: These shouldn't have min/max-inclusive
break;
/* data types not yet supported:
case com::sun::star::xsd::DataTypeClass::DURATION:
case com::sun::star::xsd::DataTypeClass::gYearMonth:
case com::sun::star::xsd::DataTypeClass::gMonthDay:
case com::sun::star::xsd::DataTypeClass::hexBinary:
case com::sun::star::xsd::DataTypeClass::base64Binary:
case com::sun::star::xsd::DataTypeClass::QName:
case com::sun::star::xsd::DataTypeClass::NOTATION:
*/
}
}
break;
default:
DBG_ERROR( "unknown facet" );
}
// finally, set the property
CreateDataType();
if( mxDataType.is()
&& sPropertyName.getLength() > 0
&& pConvert != NULL
&& mxDataType->getPropertySetInfo()->hasPropertyByName(sPropertyName) )
{
try
{
mxDataType->setPropertyValue( sPropertyName, pConvert( sValue ) );
}
catch( const Exception& )
{
; // can't set property? Then ignore.
}
}
return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
}