LibreOffice Module xmloff (master) 1
property_meta_data.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
23#include "strings.hxx"
24#include <xmloff/xmlimp.hxx>
25#include <xmloff/xmltoken.hxx>
27
28#include <o3tl/hash_combine.hxx>
29#include <tools/debug.hxx>
30#include <osl/diagnose.h>
31#include <sal/log.hxx>
32
33#include <unordered_map>
34
36{
37
38 using namespace ::xmloff::token;
39
40#define FORM_SINGLE_PROPERTY( id, att ) \
41 PropertyDescription( PROPERTY_##id, XML_NAMESPACE_FORM, att, &FormHandlerFactory::getFormPropertyHandler, PID_##id )
42
43 //= property meta data
44 namespace
45 {
46 const PropertyDescription* lcl_getPropertyMetaData()
47 {
48 static const PropertyDescription s_propertyMetaData[] =
49 {
52 FORM_SINGLE_PROPERTY( DEFAULT_DATE, XML_VALUE ),
56 FORM_SINGLE_PROPERTY( DEFAULT_TIME, XML_VALUE ),
58
59 PropertyDescription()
60 };
61 return s_propertyMetaData;
62 }
63 }
64
65 namespace
66 {
67 // TODO: instead of having all of the below static, it should be some per-instance data. This way, the
68 // approach used here would scale much better.
69 // That is, if you have multiple "meta data instances", which manage a small, but closed set of properties,
70 // then looking through those multiple instances would probably be faster than searching within
71 // one big instance, since in this case, every instance can quickly decide whether it is responsible
72 // for some attribute or property, and otherwise delegate to the next instance.
73
74 typedef std::unordered_map< OUString, const PropertyDescription* > DescriptionsByName;
75
76 const DescriptionsByName& lcl_getPropertyDescriptions()
77 {
79 static DescriptionsByName s_propertyDescriptionsByName;
80 if ( s_propertyDescriptionsByName.empty() )
81 {
82 const PropertyDescription* desc = lcl_getPropertyMetaData();
83 while ( !desc->propertyName.isEmpty() )
84 {
85 s_propertyDescriptionsByName[ desc->propertyName ] = desc;
86 ++desc;
87 }
88 }
89 return s_propertyDescriptionsByName;
90 }
91
92 typedef std::unordered_map< OUString, XMLTokenEnum > ReverseTokenLookup;
93
94 struct AttributeHash
95 {
96 size_t operator()( const AttributeDescription& i_attribute ) const
97 {
98 std::size_t seed = 0;
99 o3tl::hash_combine(seed, i_attribute.attributeToken);
100 o3tl::hash_combine(seed, i_attribute.namespacePrefix);
101 return seed;
102 }
103 };
104
105 typedef std::unordered_map< AttributeDescription, PropertyGroups, AttributeHash > AttributesWithoutGroup;
106
107 const AttributesWithoutGroup& lcl_getAttributesWithoutGroups()
108 {
110 static AttributesWithoutGroup s_attributesWithoutGroup;
111 if ( s_attributesWithoutGroup.empty() )
112 {
113 const PropertyDescription* desc = lcl_getPropertyMetaData();
114 while ( !desc->propertyName.isEmpty() )
115 {
116 PropertyDescriptionList singleElementList;
117 singleElementList.push_back( desc );
118
119 s_attributesWithoutGroup[ desc->attribute ].push_back( singleElementList );
120 ++desc;
121 }
122 }
123 return s_attributesWithoutGroup;
124 }
125 }
126
127 const PropertyDescription* getPropertyDescription( const OUString& i_propertyName )
128 {
129 const DescriptionsByName& rAllDescriptions( lcl_getPropertyDescriptions() );
130 DescriptionsByName::const_iterator pos = rAllDescriptions.find( i_propertyName );
131 if ( pos != rAllDescriptions.end() )
132 return pos->second;
133 return nullptr;
134 }
135
136 void getPropertyGroupList( const AttributeDescription& i_attribute, PropertyGroups& o_propertyGroups )
137 {
138 // the attribute is not used for any non-trivial group, which means it is mapped directly to
139 // a single property
140 const AttributesWithoutGroup& attributesWithoutGroups( lcl_getAttributesWithoutGroups() );
141 const AttributesWithoutGroup::const_iterator pos = attributesWithoutGroups.find( i_attribute );
142 if ( pos != attributesWithoutGroups.end() )
143 o_propertyGroups = pos->second;
144 }
145
147 {
149 attribute.namespacePrefix = (nAttributeToken >> NMSP_SHIFT) - 1;
150 attribute.attributeToken = static_cast<XMLTokenEnum>(nAttributeToken & TOKEN_MASK);
151 return attribute;
152 }
153
154} // namespace xmloff::metadata
155
156/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define DBG_TESTSOLARMUTEX()
DATE
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
void getPropertyGroupList(const AttributeDescription &i_attribute, PropertyGroups &o_propertyGroups)
retrieves all known property groups which are mapped to the given attribute
AttributeDescription getAttributeDescription(sal_Int32 nAttributeToken)
retrieves the attribute descriptor for the attribute given by namespace prefix and attribute name
const PropertyDescription * getPropertyDescription(const OUString &i_propertyName)
Handling of tokens in XML:
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:50
::std::vector< PropertyDescriptionList > PropertyGroups
::std::vector< const PropertyDescription * > PropertyDescriptionList
sal_Int32 attribute
#define FORM_SINGLE_PROPERTY(id, att)
size_t pos
constexpr sal_Int32 TOKEN_MASK
Definition: xmlimp.hxx:94
constexpr size_t NMSP_SHIFT
Definition: xmlimp.hxx:93