1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_xmloff.hxx"
31 #include "unointerfacetouniqueidentifiermapper.hxx"
32 
33 using ::com::sun::star::uno::Reference;
34 using ::com::sun::star::uno::XInterface;
35 using ::rtl::OUString;
36 
37 namespace comphelper
38 {
39 
40 UnoInterfaceToUniqueIdentifierMapper::UnoInterfaceToUniqueIdentifierMapper()
41 : mnNextId( 1 )
42 {
43 }
44 
45 /** returns a unique identifier for the given uno object. IF a uno object is
46 	registered more than once, the returned identifier is always the same.
47 */
48 const OUString& UnoInterfaceToUniqueIdentifierMapper::registerReference( const Reference< XInterface >& rInterface )
49 {
50 	IdMap_t::const_iterator aIter;
51 	if( findReference( rInterface, aIter ) )
52 	{
53 		return (*aIter).first;
54 	}
55 	else
56 	{
57 		OUString aId( RTL_CONSTASCII_USTRINGPARAM( "id" ) );
58 		aId += OUString::valueOf( mnNextId++ );
59 		return (*maEntries.insert( IdMap_t::value_type( aId, rInterface ) ).first).first;
60 	}
61 }
62 
63 /** registers the given uno object with the given identifier.
64 
65 	@returns
66 		false, if the given identifier already exists and is not associated with the given interface
67 */
68 bool UnoInterfaceToUniqueIdentifierMapper::registerReference( const OUString& rIdentifier, const Reference< XInterface >& rInterface )
69 {
70 	IdMap_t::const_iterator aIter;
71 	if( findReference( rInterface, aIter ) )
72 	{
73 		return rIdentifier != (*aIter).first;
74 	}
75 	else if( findIdentifier( rIdentifier, aIter ) )
76 	{
77 		return false;
78 	}
79 	else
80 	{
81 		maEntries.insert( IdMap_t::value_type( rIdentifier, rInterface ) );
82 
83 		// see if this is a reference like something we would generate in the future
84 		const sal_Unicode *p = rIdentifier.getStr();
85 		sal_Int32 nLength = rIdentifier.getLength();
86 
87 		// see if the identifier is 'id' followed by a pure integer value
88 		if( nLength < 2 || p[0] != 'i' || p[1] != 'd' )
89 			return true;
90 
91 		nLength -= 2;
92 		p += 2;
93 
94 		while(nLength--)
95 		{
96 			if( (*p < '0') || (*p > '9') )
97 				return true; // a custom id, that will never conflict with genereated id's
98 
99 			p++;
100 		}
101 
102 		// the identifier is a pure integer value
103 		// so we make sure we will never generate
104 		// an integer value like this one
105 		sal_Int32 nId = rIdentifier.copy(2).toInt32();
106 		if( mnNextId <= nId )
107 			mnNextId = nId + 1;
108 
109 		return true;
110 	}
111 }
112 
113 /** @returns
114 		the identifier for the given uno object. If this uno object is not already
115 		registered, an empty string is returned
116 */
117 const OUString& UnoInterfaceToUniqueIdentifierMapper::getIdentifier( const Reference< XInterface >& rInterface ) const
118 {
119 	IdMap_t::const_iterator aIter;
120 	if( findReference( rInterface, aIter ) )
121 	{
122 		return (*aIter).first;
123 	}
124 	else
125 	{
126 		static const OUString aEmpty;
127 		return aEmpty;
128 	}
129 }
130 
131 /** @returns
132 	the uno object that is registered with the given identifier. If no uno object
133 	is registered with the given identifier, an empty reference is returned.
134 */
135 const Reference< XInterface >& UnoInterfaceToUniqueIdentifierMapper::getReference( const OUString& rIdentifier ) const
136 {
137 	IdMap_t::const_iterator aIter;
138 	if( findIdentifier( rIdentifier, aIter ) )
139 	{
140 		return (*aIter).second;
141 	}
142 	else
143 	{
144 		static const Reference< XInterface > aEmpty;
145 		return aEmpty;
146 	}
147 }
148 
149 bool UnoInterfaceToUniqueIdentifierMapper::findReference( const Reference< XInterface >& rInterface, IdMap_t::const_iterator& rIter ) const
150 {
151 	rIter = maEntries.begin();
152 	const IdMap_t::const_iterator aEnd( maEntries.end() );
153 	while( rIter != aEnd )
154 	{
155 		if( (*rIter).second == rInterface )
156 			return true;
157 
158 		rIter++;
159 	}
160 
161 	return false;
162 }
163 
164 bool UnoInterfaceToUniqueIdentifierMapper::findIdentifier( const OUString& rIdentifier, IdMap_t::const_iterator& rIter ) const
165 {
166 	rIter = maEntries.find( rIdentifier );
167 	return rIter != maEntries.end();
168 }
169 
170 }
171 
172