1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski #include "precompiled_xmloff.hxx" 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski #include "property_description.hxx" 27*b1cdbd2cSJim Jagielski #include "forms/form_handler_factory.hxx" 28*b1cdbd2cSJim Jagielski #include "strings.hxx" 29*b1cdbd2cSJim Jagielski #include "xmloff/xmltoken.hxx" 30*b1cdbd2cSJim Jagielski #include "xmloff/xmlnmspe.hxx" 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielski #include <tools/diagnose_ex.h> 33*b1cdbd2cSJim Jagielski #include <tools/debug.hxx> 34*b1cdbd2cSJim Jagielski 35*b1cdbd2cSJim Jagielski #include <hash_map> 36*b1cdbd2cSJim Jagielski 37*b1cdbd2cSJim Jagielski //...................................................................................................................... 38*b1cdbd2cSJim Jagielski namespace xmloff { namespace metadata 39*b1cdbd2cSJim Jagielski { 40*b1cdbd2cSJim Jagielski //...................................................................................................................... 41*b1cdbd2cSJim Jagielski 42*b1cdbd2cSJim Jagielski using namespace ::xmloff::token; 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski #define FORM_SINGLE_PROPERTY( id, att ) \ 45*b1cdbd2cSJim Jagielski PropertyDescription( PROPERTY_##id, XML_NAMESPACE_FORM, att, &FormHandlerFactory::getFormPropertyHandler, PID_##id, NO_GROUP ) 46*b1cdbd2cSJim Jagielski 47*b1cdbd2cSJim Jagielski //================================================================================================================== 48*b1cdbd2cSJim Jagielski //= property meta data 49*b1cdbd2cSJim Jagielski //================================================================================================================== 50*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------------ 51*b1cdbd2cSJim Jagielski namespace 52*b1cdbd2cSJim Jagielski { lcl_getPropertyMetaData()53*b1cdbd2cSJim Jagielski const PropertyDescription* lcl_getPropertyMetaData() 54*b1cdbd2cSJim Jagielski { 55*b1cdbd2cSJim Jagielski static const PropertyDescription s_propertyMetaData[] = 56*b1cdbd2cSJim Jagielski { 57*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( DATE_MIN, XML_MIN_VALUE ), 58*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( DATE_MAX, XML_MAX_VALUE ), 59*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( DEFAULT_DATE, XML_VALUE ), 60*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( DATE, XML_CURRENT_VALUE ), 61*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( TIME_MIN, XML_MIN_VALUE ), 62*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( TIME_MAX, XML_MAX_VALUE ), 63*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( DEFAULT_TIME, XML_VALUE ), 64*b1cdbd2cSJim Jagielski FORM_SINGLE_PROPERTY( TIME, XML_CURRENT_VALUE ), 65*b1cdbd2cSJim Jagielski 66*b1cdbd2cSJim Jagielski PropertyDescription() 67*b1cdbd2cSJim Jagielski }; 68*b1cdbd2cSJim Jagielski return s_propertyMetaData; 69*b1cdbd2cSJim Jagielski } 70*b1cdbd2cSJim Jagielski } 71*b1cdbd2cSJim Jagielski 72*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------------ 73*b1cdbd2cSJim Jagielski namespace 74*b1cdbd2cSJim Jagielski { 75*b1cdbd2cSJim Jagielski // TODO: instead of having all of the below static, it should be some per-instance data. This way, the 76*b1cdbd2cSJim Jagielski // approach used here would scale much better. 77*b1cdbd2cSJim Jagielski // That is, if you have multiple "meta data instances", which manage a small, but closed set of properties, 78*b1cdbd2cSJim Jagielski // then looking looking through those multiple instances would probably be faster than searching within 79*b1cdbd2cSJim Jagielski // one big instance, since in this case, every instance can quickly decide whether it is responsible 80*b1cdbd2cSJim Jagielski // for some attribute or property, and otherwise delegate to the next instance. 81*b1cdbd2cSJim Jagielski 82*b1cdbd2cSJim Jagielski //.............................................................................................................. 83*b1cdbd2cSJim Jagielski typedef ::std::hash_map< ::rtl::OUString, const PropertyDescription*, ::rtl::OUStringHash > DescriptionsByName; 84*b1cdbd2cSJim Jagielski 85*b1cdbd2cSJim Jagielski //.............................................................................................................. lcl_getPropertyDescriptions()86*b1cdbd2cSJim Jagielski const DescriptionsByName& lcl_getPropertyDescriptions() 87*b1cdbd2cSJim Jagielski { 88*b1cdbd2cSJim Jagielski DBG_TESTSOLARMUTEX(); 89*b1cdbd2cSJim Jagielski static DescriptionsByName s_propertyDescriptionsByName; 90*b1cdbd2cSJim Jagielski if ( s_propertyDescriptionsByName.empty() ) 91*b1cdbd2cSJim Jagielski { 92*b1cdbd2cSJim Jagielski const PropertyDescription* desc = lcl_getPropertyMetaData(); 93*b1cdbd2cSJim Jagielski while ( desc->propertyName.getLength() != 0 ) 94*b1cdbd2cSJim Jagielski { 95*b1cdbd2cSJim Jagielski s_propertyDescriptionsByName[ desc->propertyName ] = desc; 96*b1cdbd2cSJim Jagielski ++desc; 97*b1cdbd2cSJim Jagielski } 98*b1cdbd2cSJim Jagielski } 99*b1cdbd2cSJim Jagielski return s_propertyDescriptionsByName; 100*b1cdbd2cSJim Jagielski } 101*b1cdbd2cSJim Jagielski 102*b1cdbd2cSJim Jagielski //.............................................................................................................. 103*b1cdbd2cSJim Jagielski typedef ::std::map< PropertyGroup, PropertyDescriptionList > IndexedPropertyGroups; 104*b1cdbd2cSJim Jagielski 105*b1cdbd2cSJim Jagielski //.............................................................................................................. lcl_getIndexedPropertyGroups()106*b1cdbd2cSJim Jagielski const IndexedPropertyGroups& lcl_getIndexedPropertyGroups() 107*b1cdbd2cSJim Jagielski { 108*b1cdbd2cSJim Jagielski DBG_TESTSOLARMUTEX(); 109*b1cdbd2cSJim Jagielski static IndexedPropertyGroups s_indexedPropertyGroups; 110*b1cdbd2cSJim Jagielski if ( s_indexedPropertyGroups.empty() ) 111*b1cdbd2cSJim Jagielski { 112*b1cdbd2cSJim Jagielski const PropertyDescription* desc = lcl_getPropertyMetaData(); 113*b1cdbd2cSJim Jagielski while ( desc->propertyName.getLength() != 0 ) 114*b1cdbd2cSJim Jagielski { 115*b1cdbd2cSJim Jagielski if ( desc->propertyGroup != NO_GROUP ) 116*b1cdbd2cSJim Jagielski s_indexedPropertyGroups[ desc->propertyGroup ].push_back( desc ); 117*b1cdbd2cSJim Jagielski ++desc; 118*b1cdbd2cSJim Jagielski } 119*b1cdbd2cSJim Jagielski } 120*b1cdbd2cSJim Jagielski return s_indexedPropertyGroups; 121*b1cdbd2cSJim Jagielski } 122*b1cdbd2cSJim Jagielski 123*b1cdbd2cSJim Jagielski //.............................................................................................................. 124*b1cdbd2cSJim Jagielski typedef ::std::hash_map< ::rtl::OUString, XMLTokenEnum, ::rtl::OUStringHash > ReverseTokenLookup; 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski //.............................................................................................................. getReverseTokenLookup()127*b1cdbd2cSJim Jagielski const ReverseTokenLookup& getReverseTokenLookup() 128*b1cdbd2cSJim Jagielski { 129*b1cdbd2cSJim Jagielski DBG_TESTSOLARMUTEX(); 130*b1cdbd2cSJim Jagielski static ReverseTokenLookup s_reverseTokenLookup; 131*b1cdbd2cSJim Jagielski if ( s_reverseTokenLookup.empty() ) 132*b1cdbd2cSJim Jagielski { 133*b1cdbd2cSJim Jagielski const PropertyDescription* desc = lcl_getPropertyMetaData(); 134*b1cdbd2cSJim Jagielski while ( desc->propertyName.getLength() != 0 ) 135*b1cdbd2cSJim Jagielski { 136*b1cdbd2cSJim Jagielski s_reverseTokenLookup[ token::GetXMLToken( desc->attribute.attributeToken ) ] = desc->attribute.attributeToken; 137*b1cdbd2cSJim Jagielski ++desc; 138*b1cdbd2cSJim Jagielski } 139*b1cdbd2cSJim Jagielski } 140*b1cdbd2cSJim Jagielski return s_reverseTokenLookup; 141*b1cdbd2cSJim Jagielski } 142*b1cdbd2cSJim Jagielski 143*b1cdbd2cSJim Jagielski //.............................................................................................................. 144*b1cdbd2cSJim Jagielski struct AttributeHash : public ::std::unary_function< AttributeDescription, size_t > 145*b1cdbd2cSJim Jagielski { operator ()xmloff::metadata::__anon25524f150211::AttributeHash146*b1cdbd2cSJim Jagielski size_t operator()( const AttributeDescription& i_attribute ) const 147*b1cdbd2cSJim Jagielski { 148*b1cdbd2cSJim Jagielski return size_t( i_attribute.attributeToken * 100 ) + size_t( i_attribute.namespacePrefix ); 149*b1cdbd2cSJim Jagielski } 150*b1cdbd2cSJim Jagielski }; 151*b1cdbd2cSJim Jagielski 152*b1cdbd2cSJim Jagielski //.............................................................................................................. 153*b1cdbd2cSJim Jagielski typedef ::std::hash_multimap< AttributeDescription, PropertyGroup, AttributeHash > AttributeGroups; 154*b1cdbd2cSJim Jagielski 155*b1cdbd2cSJim Jagielski //.............................................................................................................. lcl_getAttributeGroups()156*b1cdbd2cSJim Jagielski const AttributeGroups& lcl_getAttributeGroups() 157*b1cdbd2cSJim Jagielski { 158*b1cdbd2cSJim Jagielski DBG_TESTSOLARMUTEX(); 159*b1cdbd2cSJim Jagielski static AttributeGroups s_attributeGroups; 160*b1cdbd2cSJim Jagielski if ( s_attributeGroups.empty() ) 161*b1cdbd2cSJim Jagielski { 162*b1cdbd2cSJim Jagielski const PropertyDescription* desc = lcl_getPropertyMetaData(); 163*b1cdbd2cSJim Jagielski while ( desc->propertyName.getLength() != 0 ) 164*b1cdbd2cSJim Jagielski { 165*b1cdbd2cSJim Jagielski if ( desc->propertyGroup != NO_GROUP ) 166*b1cdbd2cSJim Jagielski s_attributeGroups.insert( AttributeGroups::value_type( desc->attribute, desc->propertyGroup ) ); 167*b1cdbd2cSJim Jagielski ++desc; 168*b1cdbd2cSJim Jagielski } 169*b1cdbd2cSJim Jagielski } 170*b1cdbd2cSJim Jagielski return s_attributeGroups; 171*b1cdbd2cSJim Jagielski } 172*b1cdbd2cSJim Jagielski 173*b1cdbd2cSJim Jagielski //.............................................................................................................. 174*b1cdbd2cSJim Jagielski typedef ::std::hash_map< AttributeDescription, PropertyGroups, AttributeHash > AttributesWithoutGroup; 175*b1cdbd2cSJim Jagielski 176*b1cdbd2cSJim Jagielski //.............................................................................................................. lcl_getAttributesWithoutGroups()177*b1cdbd2cSJim Jagielski const AttributesWithoutGroup& lcl_getAttributesWithoutGroups() 178*b1cdbd2cSJim Jagielski { 179*b1cdbd2cSJim Jagielski DBG_TESTSOLARMUTEX(); 180*b1cdbd2cSJim Jagielski static AttributesWithoutGroup s_attributesWithoutGroup; 181*b1cdbd2cSJim Jagielski if ( s_attributesWithoutGroup.empty() ) 182*b1cdbd2cSJim Jagielski { 183*b1cdbd2cSJim Jagielski const PropertyDescription* desc = lcl_getPropertyMetaData(); 184*b1cdbd2cSJim Jagielski while ( desc->propertyName.getLength() != 0 ) 185*b1cdbd2cSJim Jagielski { 186*b1cdbd2cSJim Jagielski if ( desc->propertyGroup == NO_GROUP ) 187*b1cdbd2cSJim Jagielski { 188*b1cdbd2cSJim Jagielski PropertyDescriptionList singleElementList; 189*b1cdbd2cSJim Jagielski singleElementList.push_back( desc ); 190*b1cdbd2cSJim Jagielski 191*b1cdbd2cSJim Jagielski s_attributesWithoutGroup[ desc->attribute ].push_back( singleElementList ); 192*b1cdbd2cSJim Jagielski } 193*b1cdbd2cSJim Jagielski ++desc; 194*b1cdbd2cSJim Jagielski } 195*b1cdbd2cSJim Jagielski } 196*b1cdbd2cSJim Jagielski return s_attributesWithoutGroup; 197*b1cdbd2cSJim Jagielski } 198*b1cdbd2cSJim Jagielski } 199*b1cdbd2cSJim Jagielski 200*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------------ getPropertyDescription(const::rtl::OUString & i_propertyName)201*b1cdbd2cSJim Jagielski const PropertyDescription* getPropertyDescription( const ::rtl::OUString& i_propertyName ) 202*b1cdbd2cSJim Jagielski { 203*b1cdbd2cSJim Jagielski const DescriptionsByName& rAllDescriptions( lcl_getPropertyDescriptions() ); 204*b1cdbd2cSJim Jagielski DescriptionsByName::const_iterator pos = rAllDescriptions.find( i_propertyName ); 205*b1cdbd2cSJim Jagielski if ( pos != rAllDescriptions.end() ) 206*b1cdbd2cSJim Jagielski return pos->second; 207*b1cdbd2cSJim Jagielski return NULL; 208*b1cdbd2cSJim Jagielski } 209*b1cdbd2cSJim Jagielski 210*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------------ getPropertyGroup(const PropertyGroup i_propertyGroup,PropertyDescriptionList & o_propertyDescriptions)211*b1cdbd2cSJim Jagielski void getPropertyGroup( const PropertyGroup i_propertyGroup, PropertyDescriptionList& o_propertyDescriptions ) 212*b1cdbd2cSJim Jagielski { 213*b1cdbd2cSJim Jagielski OSL_ENSURE( i_propertyGroup != NO_GROUP, "xmloff::metadata::getPropertyGroup: illegal group!" ); 214*b1cdbd2cSJim Jagielski 215*b1cdbd2cSJim Jagielski const IndexedPropertyGroups& rPropertyGroups( lcl_getIndexedPropertyGroups() ); 216*b1cdbd2cSJim Jagielski const IndexedPropertyGroups::const_iterator pos = rPropertyGroups.find( i_propertyGroup ); 217*b1cdbd2cSJim Jagielski if ( pos != rPropertyGroups.end() ) 218*b1cdbd2cSJim Jagielski o_propertyDescriptions = pos->second; 219*b1cdbd2cSJim Jagielski } 220*b1cdbd2cSJim Jagielski 221*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------------ getPropertyGroupList(const AttributeDescription & i_attribute,PropertyGroups & o_propertyGroups)222*b1cdbd2cSJim Jagielski void getPropertyGroupList( const AttributeDescription& i_attribute, PropertyGroups& o_propertyGroups ) 223*b1cdbd2cSJim Jagielski { 224*b1cdbd2cSJim Jagielski const AttributeGroups& rAttributeGroups = lcl_getAttributeGroups(); 225*b1cdbd2cSJim Jagielski 226*b1cdbd2cSJim Jagielski ::std::pair< AttributeGroups::const_iterator, AttributeGroups::const_iterator > 227*b1cdbd2cSJim Jagielski range = rAttributeGroups.equal_range( i_attribute ); 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski if ( range.first == range.second ) 230*b1cdbd2cSJim Jagielski { 231*b1cdbd2cSJim Jagielski // the attribute is not used for any non-trivial group, which means it is mapped directly to 232*b1cdbd2cSJim Jagielski // a single property 233*b1cdbd2cSJim Jagielski const AttributesWithoutGroup& attributesWithoutGroups( lcl_getAttributesWithoutGroups() ); 234*b1cdbd2cSJim Jagielski const AttributesWithoutGroup::const_iterator pos = attributesWithoutGroups.find( i_attribute ); 235*b1cdbd2cSJim Jagielski if ( pos != attributesWithoutGroups.end() ) 236*b1cdbd2cSJim Jagielski o_propertyGroups = pos->second; 237*b1cdbd2cSJim Jagielski } 238*b1cdbd2cSJim Jagielski else 239*b1cdbd2cSJim Jagielski { 240*b1cdbd2cSJim Jagielski const IndexedPropertyGroups& rPropertyGroups = lcl_getIndexedPropertyGroups(); 241*b1cdbd2cSJim Jagielski for ( AttributeGroups::const_iterator group = range.first; group != range.second; ++group ) 242*b1cdbd2cSJim Jagielski { 243*b1cdbd2cSJim Jagielski const PropertyGroup propGroup = group->second; 244*b1cdbd2cSJim Jagielski const IndexedPropertyGroups::const_iterator groupPos = rPropertyGroups.find( propGroup ); 245*b1cdbd2cSJim Jagielski ENSURE_OR_CONTINUE( groupPos != rPropertyGroups.end(), "getPropertyGroupList: inconsistency!" ); 246*b1cdbd2cSJim Jagielski o_propertyGroups.push_back( groupPos->second ); 247*b1cdbd2cSJim Jagielski } 248*b1cdbd2cSJim Jagielski } 249*b1cdbd2cSJim Jagielski } 250*b1cdbd2cSJim Jagielski 251*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------------ getAttributeDescription(const sal_uInt16 i_namespacePrefix,const::rtl::OUString & i_attributeName)252*b1cdbd2cSJim Jagielski AttributeDescription getAttributeDescription( const sal_uInt16 i_namespacePrefix, const ::rtl::OUString& i_attributeName ) 253*b1cdbd2cSJim Jagielski { 254*b1cdbd2cSJim Jagielski AttributeDescription attribute; 255*b1cdbd2cSJim Jagielski const ReverseTokenLookup& rTokenLookup( getReverseTokenLookup() ); 256*b1cdbd2cSJim Jagielski const ReverseTokenLookup::const_iterator pos = rTokenLookup.find( i_attributeName ); 257*b1cdbd2cSJim Jagielski if ( pos != rTokenLookup.end() ) 258*b1cdbd2cSJim Jagielski { 259*b1cdbd2cSJim Jagielski attribute.namespacePrefix = i_namespacePrefix; 260*b1cdbd2cSJim Jagielski attribute.attributeToken = pos->second; 261*b1cdbd2cSJim Jagielski } 262*b1cdbd2cSJim Jagielski return attribute; 263*b1cdbd2cSJim Jagielski } 264*b1cdbd2cSJim Jagielski 265*b1cdbd2cSJim Jagielski //...................................................................................................................... 266*b1cdbd2cSJim Jagielski } } // namespace xmloff::metadata 267*b1cdbd2cSJim Jagielski //...................................................................................................................... 268