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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 
31 #include "MacabAddressBook.hxx"
32 #include "MacabRecords.hxx"
33 #include "MacabGroup.hxx"
34 
35 #include <vector>
36 
37 #include <premac.h>
38 #include <Carbon/Carbon.h>
39 #include <AddressBook/ABAddressBookC.h>
40 #include <postmac.h>
41 #include "connectivity/CommonTools.hxx"
42 
43 using namespace connectivity::macab;
44 using namespace ::com::sun::star::uno;
45 
46 // -----------------------------------------------------------------------------
47 MacabAddressBook::MacabAddressBook( )
48 {
49 	m_aAddressBook = ABGetSharedAddressBook();
50 	m_xMacabRecords = NULL;
51 	m_bRetrievedGroups = sal_False;
52 }
53 
54 // -----------------------------------------------------------------------------
55 MacabAddressBook::~MacabAddressBook()
56 {
57 	if(m_xMacabRecords != NULL)
58 	{
59 		delete m_xMacabRecords;
60 		m_xMacabRecords = NULL;
61 	}
62 
63 	if(!m_xMacabGroups.empty())
64 	{
65 		::std::vector<MacabGroup *>::iterator iter, end;
66 		iter = m_xMacabGroups.begin();
67 		end = m_xMacabGroups.end();
68 		for( ; iter != end; ++iter)
69 			delete (*iter);
70 	}
71 
72 	m_bRetrievedGroups = sal_False;
73 }
74 
75 // -----------------------------------------------------------------------------
76 /* Get the address book's default table name. This is the table name that
77  * refers to the table containing _all_ records in the address book.
78  */
79 const ::rtl::OUString & MacabAddressBook::getDefaultTableName()
80 {
81 	/* This string probably needs to be localized. */
82 	static const ::rtl::OUString aDefaultTableName
83 		(::rtl::OUString::createFromAscii("Address Book"));
84 
85 	return aDefaultTableName;
86 }
87 
88 // -----------------------------------------------------------------------------
89 MacabRecords *MacabAddressBook::getMacabRecords()
90 {
91 	/* If the MacabRecords don't exist, create them. */
92 	if(m_xMacabRecords == NULL)
93 	{
94 		m_xMacabRecords = new MacabRecords(m_aAddressBook);
95 		m_xMacabRecords->setName(getDefaultTableName());
96 		m_xMacabRecords->initialize();
97 	}
98 
99 	return m_xMacabRecords;
100 }
101 
102 // -----------------------------------------------------------------------------
103 /* Get the MacabRecords for a given name: either a group name or the
104  * default table name.
105  */
106 MacabRecords *MacabAddressBook::getMacabRecords(const ::rtl::OUString _tableName)
107 {
108 	if(_tableName == getDefaultTableName())
109 	{
110 		return getMacabRecords();
111 	}
112 	else
113 	{
114 		return getMacabGroup(_tableName);
115 	}
116 }
117 
118 // -----------------------------------------------------------------------------
119 MacabRecords *MacabAddressBook::getMacabRecordsMatch(const ::rtl::OUString _tableName)
120 {
121 	if(match(_tableName, getDefaultTableName(), '\0'))
122 	{
123 		return getMacabRecords();
124 	}
125 
126 	return getMacabGroupMatch(_tableName);
127 }
128 
129 // -----------------------------------------------------------------------------
130 ::std::vector<MacabGroup *> MacabAddressBook::getMacabGroups()
131 {
132 	/* If the MacabGroups haven't been created yet, create them. */
133 	if(m_bRetrievedGroups == sal_False)
134 	{
135 		/* If the MacabRecords haven't been created yet, create them. */
136 		if(m_xMacabRecords == NULL)
137 		{
138 			m_xMacabRecords = new MacabRecords(m_aAddressBook);
139 			m_xMacabRecords->setName(getDefaultTableName());
140 			m_xMacabRecords->initialize();
141 		}
142 
143 		CFArrayRef allGroups = ABCopyArrayOfAllGroups(m_aAddressBook);
144 		sal_Int32 nGroups = CFArrayGetCount(allGroups);
145 		m_xMacabGroups = ::std::vector<MacabGroup *>(nGroups);
146 
147 		sal_Int32 i;
148 		ABGroupRef xGroup;
149 
150 		/* Go through each group and create a MacabGroup out of it. */
151 		for(i = 0; i < nGroups; i++)
152 		{
153 			xGroup = (ABGroupRef) CFArrayGetValueAtIndex(allGroups, i);
154 			m_xMacabGroups[i] = new MacabGroup(m_aAddressBook, m_xMacabRecords, xGroup);
155 		}
156 
157 		CFRelease(allGroups);
158 
159 		/* Manage duplicates. */
160 		manageDuplicateGroups(m_xMacabGroups);
161 		m_bRetrievedGroups = sal_True;
162 	}
163 
164 	return m_xMacabGroups;
165 }
166 
167 // -----------------------------------------------------------------------------
168 MacabGroup *MacabAddressBook::getMacabGroup(::rtl::OUString _groupName)
169 {
170 	// initialize groups if not already initialized
171 	if(m_bRetrievedGroups == sal_False)
172 		getMacabGroups();
173 
174 	sal_Int32 nGroups = m_xMacabGroups.size();
175 	sal_Int32 i;
176 
177 	for(i = 0; i < nGroups; i++)
178 	{
179 		if(m_xMacabGroups[i] != NULL)
180 		{
181 			if(m_xMacabGroups[i]->getName() == _groupName)
182 			{
183 				return m_xMacabGroups[i];
184 			}
185 		}
186 	}
187 
188 	return NULL;
189 }
190 
191 // -----------------------------------------------------------------------------
192 MacabGroup *MacabAddressBook::getMacabGroupMatch(::rtl::OUString _groupName)
193 {
194 	// initialize groups if not already initialized
195 	if(m_bRetrievedGroups == sal_False)
196 		getMacabGroups();
197 
198 	sal_Int32 nGroups = m_xMacabGroups.size();
199 	sal_Int32 i;
200 
201 	for(i = 0; i < nGroups; i++)
202 	{
203 		if(m_xMacabGroups[i] != NULL)
204 		{
205 			if(match(m_xMacabGroups[i]->getName(), _groupName, '\0'))
206 			{
207 				return m_xMacabGroups[i];
208 			}
209 		}
210 	}
211 
212 	return NULL;
213 }
214 
215 // -------------------------------------------------------------------------
216 void MacabAddressBook::manageDuplicateGroups(::std::vector<MacabGroup *> _xGroups) const
217 {
218 	/* If we have two cases of groups, say, family, this makes it:
219 	 * family
220 	 * family (2)
221 	 */
222 	::std::vector<MacabGroup *>::reverse_iterator iter1, iter2;
223 	sal_Int32 count;
224 
225 	for(iter1 = _xGroups.rbegin(); iter1 != _xGroups.rend(); ++iter1)
226 	{
227 		/* If the name matches the default table name, there is already
228 		 * (obviously) a conflict. So, start the count of groups with this
229 		 * name at 2 instead of 1.
230 		 */
231 		if( (*iter1)->getName() == getDefaultTableName() )
232 			count = 2;
233 		else
234 			count = 1;
235 
236 		iter2 = iter1;
237 		for( ++iter2; iter2 != _xGroups.rend(); ++iter2)
238 		{
239 			if( (*iter1)->getName() == (*iter2)->getName() )
240 			{
241 				count++;
242 			}
243 		}
244 
245 		// duplicate!
246 		if(count != 1)
247 		{
248 			::rtl::OUString sName = (*iter1)->getName();
249 			sName += ::rtl::OUString::createFromAscii(" (") +
250 				::rtl::OUString::valueOf(count) +
251 				::rtl::OUString::createFromAscii(")");
252 			(*iter1)->setName(sName);
253 		}
254 	}
255 }
256 
257