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