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 #include <osl/interlck.h>
29 #include	<rtl/alloc.h>
30 #include	<codemaker/dependency.hxx>
31 
32 using namespace rtl;
33 
34 TypeDependency::TypeDependency()
35 {
36 	m_pImpl = new TypeDependencyImpl();
37 	acquire();
38 }
39 
40 TypeDependency::~TypeDependency()
41 {
42 	release();
43 }
44 
45 void TypeDependency::acquire()
46 {
47 	osl_incrementInterlockedCount(&m_pImpl->m_refCount);
48 }
49 
50 void TypeDependency::release()
51 {
52 	if (0 == osl_decrementInterlockedCount(&m_pImpl->m_refCount))
53 	{
54 		delete m_pImpl;
55 	}
56 }
57 
58 sal_Bool TypeDependency::insert(const OString& type, const OString& depend, sal_uInt16 use)
59 {
60 	sal_Bool ret =  sal_False;
61 
62 	if (type.getLength() > 0 && depend.getLength() > 0)
63 	{
64 		if (m_pImpl->m_dependencies.count(type) > 0)
65 		{
66 			TypeUsing typeUsing(depend, use);
67 			TypeUsingSet::iterator iter;
68 			if ((iter = m_pImpl->m_dependencies[type].find(typeUsing)) != m_pImpl->m_dependencies[type].end())
69 			{
70   				(((TypeUsing *) &(*iter))->m_use) = (*iter).m_use | use;
71 			} else
72 			{
73 				m_pImpl->m_dependencies[type].insert(typeUsing);
74 			}
75 		} else
76 		{
77 			TypeUsing typeUsing(depend, use);
78 			TypeUsingSet tmpSet;
79 			tmpSet.insert(typeUsing);
80 			m_pImpl->m_dependencies[type]=tmpSet;
81 		}
82 	}
83 
84 	return ret;
85 }
86 
87 TypeUsingSet TypeDependency::getDependencies(const OString& type)
88 {
89 	if (type.getLength() > 0)
90 	{
91 		if (m_pImpl->m_dependencies.count(type) > 0)
92 		{
93 			return m_pImpl->m_dependencies[type];
94 		}
95 	}
96 
97 	return TypeUsingSet();
98 }
99 
100 sal_Bool TypeDependency::hasDependencies(const OString& type)
101 {
102 	if (type.getLength() > 0)
103 	{
104 		if (m_pImpl->m_dependencies.count(type) > 0)
105 		{
106 			return sal_True;
107 		}
108 	}
109 
110 	return sal_False;
111 }
112 
113 void TypeDependency::setGenerated(const OString& type, sal_uInt16 genFlag)
114 {
115 //	m_pImpl->m_generatedTypes.insert(type);
116 	if (m_pImpl->m_generatedTypes.count(type) > 0)
117 		m_pImpl->m_generatedTypes[type]= m_pImpl->m_generatedTypes[type] | genFlag;
118 	else
119 		m_pImpl->m_generatedTypes[type]=genFlag;
120 }
121 
122 sal_Bool TypeDependency::isGenerated(const OString& type, sal_uInt16 genFlag)
123 {
124 /*
125 	if (m_pImpl->m_generatedTypes.count(type) > 0)
126 		return sal_True;
127 
128 	return sal_False;
129 */
130 	if (m_pImpl->m_generatedTypes.count(type) > 0 &&
131 		m_pImpl->m_generatedTypes[type] & genFlag)
132 	{
133 		return sal_True;
134 	}
135 
136 	return sal_False;
137 }
138 
139 static sal_Bool checkFieldDependencies(TypeManager& typeMgr, TypeDependency& dependencies,
140 									   TypeReader& reader, const OString& type)
141 {
142 	sal_uInt32 count = reader.getFieldCount();
143 
144 	if (count == 0 || reader.getTypeClass() == RT_TYPE_ENUM)
145 		return sal_True;
146 
147 	OString fieldType;
148 	for (sal_uInt16 i=0; i < count; i++)
149 	{
150 		fieldType = reader.getFieldType(i);
151 
152 		if (fieldType.getLength() > 0)
153 		{
154 			dependencies.insert(type, fieldType, TYPEUSE_MEMBER);
155 			checkTypeDependencies(typeMgr, dependencies, fieldType);
156 		}
157 	}
158 
159 	return sal_True;
160 }
161 
162 static sal_Bool checkMethodDependencies(TypeManager& typeMgr, TypeDependency& dependencies,
163 									    TypeReader& reader, const OString& type)
164 {
165 	sal_uInt32 count = reader.getMethodCount();
166 
167 	if (count == 0)
168 		return sal_True;
169 
170 	OString returnType, paramType, excType;
171 	sal_uInt32 paramCount = 0;
172 	sal_uInt32 excCount = 0;
173 	RTParamMode paramMode = RT_PARAM_INVALID;
174 	for (sal_uInt16 i=0; i < count; i++)
175 	{
176 		returnType = reader.getMethodReturnType(i);
177 
178 		dependencies.insert(type, returnType, TYPEUSE_RETURN);
179 		checkTypeDependencies(typeMgr, dependencies, returnType);
180 
181 		paramCount = reader.getMethodParamCount(i);
182 		excCount = reader.getMethodExcCount(i);
183 
184 		sal_uInt16 j;
185 		for (j=0; j < paramCount; j++)
186 		{
187 			paramType = reader.getMethodParamType(i, j);
188 			paramMode = reader.getMethodParamMode(i, j);
189 
190 			switch (paramMode)
191 			{
192 				case RT_PARAM_IN:
193 					dependencies.insert(type, paramType, TYPEUSE_INPARAM);
194 					break;
195 				case RT_PARAM_OUT:
196 					dependencies.insert(type, paramType, TYPEUSE_OUTPARAM);
197 					break;
198 				case RT_PARAM_INOUT:
199 					dependencies.insert(type, paramType, TYPEUSE_INOUTPARAM);
200 					break;
201                 default:
202                     break;
203 			}
204 
205 			checkTypeDependencies(typeMgr, dependencies, paramType);
206 		}
207 
208 		for (j=0; j < excCount; j++)
209 		{
210 			excType = reader.getMethodExcType(i, j);
211 			dependencies.insert(type, excType, TYPEUSE_EXCEPTION);
212 			checkTypeDependencies(typeMgr, dependencies, excType);
213 		}
214 
215 	}
216 
217 	return sal_True;
218 }
219 
220 static sal_Bool checkReferenceDependencies(TypeManager& typeMgr, TypeDependency& dependencies,
221 										   TypeReader& reader, const OString& type)
222 {
223 	sal_uInt32 count = reader.getReferenceCount();
224 
225 	if (count == 0)
226 		return sal_True;
227 
228 	OString referenceName;
229 	for (sal_uInt16 i=0; i < count; i++)
230 	{
231 		referenceName = reader.getReferenceName(i);
232 
233 		dependencies.insert(type, referenceName, TYPEUSE_NORMAL);
234 		checkTypeDependencies(typeMgr, dependencies, referenceName);
235 	}
236 
237 	return sal_True;
238 }
239 
240 sal_Bool checkTypeDependencies(TypeManager& typeMgr, TypeDependency& dependencies, const OString& type, sal_Bool bDepend)
241 {
242 	if (!typeMgr.isValidType(type))
243 		return sal_False;
244 
245 	if (dependencies.hasDependencies(type))
246 		return sal_True;
247 
248 	TypeReader reader = typeMgr.getTypeReader(type);
249 
250 	if ( !reader.isValid() )
251 	{
252 		if (type.equals("/"))
253 			return sal_True;
254 		else
255 			return sal_False;
256 	}
257 
258     if ( bDepend && reader.getTypeClass() == RT_TYPE_MODULE)
259     {
260     	checkFieldDependencies(typeMgr, dependencies, reader, type);
261         return sal_True;
262     }
263 
264     for (sal_uInt16 i = 0; i < reader.getSuperTypeCount(); ++i) {
265         OString superType(reader.getSuperTypeName(i));
266 		dependencies.insert(type, superType, TYPEUSE_SUPER);
267 		checkTypeDependencies(typeMgr, dependencies, superType);
268 	}
269 
270 	if (reader.getTypeClass() == RT_TYPE_INTERFACE)
271 	{
272 		dependencies.insert(type, "com/sun/star/uno/RuntimeException", TYPEUSE_EXCEPTION);
273 		dependencies.insert(type, "com/sun/star/uno/TypeClass", TYPEUSE_NORMAL);
274 		checkTypeDependencies(typeMgr, dependencies, "com/sun/star/uno/RuntimeException", bDepend);
275 	}
276 
277 	checkFieldDependencies(typeMgr, dependencies, reader, type);
278 	checkMethodDependencies(typeMgr, dependencies, reader, type);
279 	checkReferenceDependencies(typeMgr, dependencies, reader, type);
280 
281     // make the scope modules as dependencies
282     sal_Int32 nPos = type.lastIndexOf( '/' );
283 
284 	if ( nPos >= 0 )
285 	{
286 		OString aScope( type.copy( 0, nPos ) );
287 		OStringBuffer tmpBuf(aScope.getLength());
288 
289 		nPos = 0;
290 		do
291 		{
292 			tmpBuf.append(aScope.getToken(0, '/', nPos));
293 			dependencies.insert(type, tmpBuf.getStr(), TYPEUSE_SCOPE);
294 			tmpBuf.append('/');
295 		} while( nPos != -1 );
296     }
297 
298 	return sal_True;
299 }
300 
301 
302