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