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