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 <precomp.h>
29 #include "c_reposypart.hxx"
30 
31 
32 // NOT FULLY DECLARED SERVICES
33 #include <ary/getncast.hxx>
34 #include <ary/namesort.hxx>
35 #include <ary/cpp/c_builtintype.hxx>
36 #include <ary/cpp/c_class.hxx>
37 #include <ary/cpp/c_cppentity.hxx>
38 #include <ary/cpp/c_define.hxx>
39 #include <ary/cpp/c_enum.hxx>
40 #include <ary/cpp/c_enuval.hxx>
41 #include <ary/cpp/c_funct.hxx>
42 #include <ary/cpp/c_macro.hxx>
43 #include <ary/cpp/c_namesp.hxx>
44 #include <ary/cpp/c_tydef.hxx>
45 #include <ary/cpp/c_type.hxx>
46 #include <ary/cpp/usedtype.hxx>
47 #include <ary/cpp/c_vari.hxx>
48 #include <ary/loc/locp_le.hxx>
49 #include <ary/getncast.hxx>
50 #include <loc_internalgate.hxx>
51 #include <reposy.hxx>
52 #include "ca_ce.hxx"
53 #include "ca_def.hxx"
54 #include "ca_type.hxx"
55 #include "cs_ce.hxx"
56 #include "cs_def.hxx"
57 #include "cs_type.hxx"
58 
59 
60 
61 namespace
62 {
63 
64 using ::ary::GlobalId;
65 using ::ary::Rid;
66 using namespace ::ary::cpp;
67 
68 
69 inline bool
70 IsDefine( const GlobalId & i_id )
71 {
72     return i_id.Class() == Define::class_id
73            OR
74            i_id.Class() == Macro::class_id;
75 }
76 
77 
78 /// Find Ces
79 class TypeConnector
80 {
81   public:
82                         TypeConnector(
83                             Gate &              i_gate )
84                             :   pGate(&i_gate) {}
85                         ~TypeConnector() {}
86 
87     void                operator()(
88                             Type &              io_rType ) const;
89   private:
90     // DATA
91     Gate *              pGate;
92 };
93 
94 /// Find Ces only known from base class name scope.
95 class TypeConnector2ndTry
96 {
97   public:
98                         TypeConnector2ndTry(
99                             Gate &              i_gate )
100                             :   pGate(&i_gate) {}
101                         ~TypeConnector2ndTry() {}
102 
103     void                operator()(
104                             Type &              io_rType ) const;
105   private:
106     // DATA
107     Gate *              pGate;
108 };
109 
110 /// Reconnect (in both directions) base-derived relations of classes.
111 class HierarchyLinker
112 {
113   public:
114                         HierarchyLinker(
115                             Gate &              i_gate )
116                             :   pGate(&i_gate) {}
117 
118                         ~HierarchyLinker() {}
119 
120     void                operator()(
121                             Class &             io_rCe ) const;
122   private:
123     // DATA
124     Gate *              pGate;
125 };
126 
127 
128 
129 /// Helper functor for ->RepositoryPartition::Get_AlphabeticalList().
130 template <class TRAITS>
131 struct MakeGlobalId
132 {
133     GlobalId            operator()(
134                             typename TRAITS::id_type
135                                                 i_id ) const
136                         {
137                             return GlobalId( TRAITS::EntityOf_(i_id).AryClass(),
138                                              i_id.Value() );
139                         }
140 };
141 
142 
143 
144 
145 /** Compare two {->GlobalId}s.
146 
147 
148     @todo   Move this up to the definition of GlobalId<>.
149 */
150 struct LesserGlobal
151 {
152                         LesserGlobal(
153                             const Ce_Storage &  i_ces,
154                             const Def_Storage & i_des )
155                             :   rCes(i_ces), rDes(i_des) {}
156 
157     bool                operator()(
158                             GlobalId            i_1,
159                             GlobalId            i_2 ) const;
160 
161   private:
162     const String &      NameOf(
163                             GlobalId            i_id ) const;
164     // DATA
165     const Ce_Storage &  rCes;
166     const Def_Storage & rDes;
167     ::ary::LesserName   aLess;
168 };
169 
170 
171 bool
172 LesserGlobal::operator()(   GlobalId            i_1,
173                             GlobalId            i_2 ) const
174                         {
175                             String  s1 = NameOf(i_1);
176                             String  s2 = NameOf(i_2);
177 
178                             if (s1 != s2)
179                                 return aLess(s1, s2);
180 
181                             if ( IsDefine(i_1) != IsDefine(i_2) )
182                             {
183                                 return NOT IsDefine(i_2);
184                             }
185                             else if (IsDefine(i_1))
186                             {
187                                 return i_1.Class() < i_2.Class();
188                             }
189 
190                             return Ce_GlobalCompare::Lesser_(
191                                         rCes[i_1.Id()],
192                                         rCes[i_2.Id()] );
193                         }
194 
195 
196 }   // namespace anonymous
197 
198 
199 
200 
201 
202 
203 namespace ary
204 {
205 namespace cpp
206 {
207 
208 DYN InternalGate &
209 InternalGate::Create_Partition_(RepositoryCenter & i_center)
210 {
211     return *new RepositoryPartition(i_center);
212 }
213 
214 
215 RepositoryPartition::RepositoryPartition(RepositoryCenter & i_center)
216     :   pRepositoryCenter(&i_center),
217         pCes(0),
218         pTypes(0),
219         pDefs(0),
220         pLocations(& loc::InternalGate::Create_Locations_())
221 {
222     pCes        = new CeAdmin(*this);
223     pTypes      = new TypeAdmin(*this);
224     pDefs       = new DefAdmin(*this);
225     pCes->Set_Related(*pTypes);
226 }
227 
228 RepositoryPartition::~RepositoryPartition()
229 {
230 }
231 
232 void
233 RepositoryPartition::Calculate_AllSecondaryInformation()
234 //                                        const ::autodoc::Options & )
235 {
236     // KORR_FUTURE
237     //  Forward the options from here.
238 
239     Connect_AllTypes_2_TheirRelated_CodeEntites();
240 }
241 
242 const String &
243 RepositoryPartition::RepositoryTitle() const
244 {
245     return static_cast< ary::Repository* >(pRepositoryCenter)->Title();
246 }
247 
248 const CodeEntity *
249 RepositoryPartition::Search_RelatedCe(Type_id i_type) const
250 {
251     if (NOT i_type.IsValid())
252         return 0;
253 
254     Ce_id
255         ce_id = pTypes->Find_Type(i_type).RelatedCe();
256     return ce_id.IsValid()
257                 ?   & pCes->Find_Ce(ce_id)
258                 :   (CodeEntity*)(0);
259 }
260 
261 const ::ary::cpp::CppEntity *
262 RepositoryPartition::Search_Entity(GlobalId i_id) const
263 {
264     if (i_id.Id() == 0)
265         return 0;
266 
267     if ( NOT IsDefine(i_id) )
268     {
269         // Shall make sure this is a C++ CodeEntity:
270         csv_assert( i_id.Class() >= Namespace::class_id
271                     AND
272                     i_id.Class() < BuiltInType::class_id
273                     && "Unexpected entity type in cpp::RepositoryPartition"
274                        "::Search_Entity()." );
275         return & Ces().Find_Ce( Ce_id(i_id.Id()) );
276     }
277     else
278     {
279         return & Defs().Find_Def( De_id(i_id.Id()) );
280     }
281 }
282 
283 
284 const CePilot &
285 RepositoryPartition::Ces() const
286 {
287     csv_assert(pCes != 0);
288     return *pCes;
289 }
290 
291 const DefPilot &
292 RepositoryPartition::Defs() const
293 {
294     csv_assert(pDefs != 0);
295     return *pDefs;
296 }
297 
298 const TypePilot &
299 RepositoryPartition::Types() const
300 {
301     csv_assert(pTypes != 0);
302     return *pTypes;
303 }
304 
305 const loc::LocationPilot &
306 RepositoryPartition::Locations() const
307 {
308     csv_assert(pLocations != 0);
309     return *pLocations;
310 }
311 
312 CePilot &
313 RepositoryPartition::Ces()
314 {
315     csv_assert(pCes != 0);
316     return *pCes;
317 }
318 
319 DefPilot &
320 RepositoryPartition::Defs()
321 {
322     csv_assert(pDefs != 0);
323     return *pDefs;
324 }
325 
326 TypePilot &
327 RepositoryPartition::Types()
328 {
329     csv_assert(pTypes != 0);
330     return *pTypes;
331 }
332 
333 loc::LocationPilot &
334 RepositoryPartition::Locations()
335 {
336     csv_assert(pLocations != 0);
337     return *pLocations;
338 }
339 
340 
341 void
342 RepositoryPartition::Connect_AllTypes_2_TheirRelated_CodeEntites()
343 {
344     TypeConnector
345         aConnector(*this);
346     std::for_each( pTypes->Storage().BeginUnreserved(),
347                    pTypes->Storage().End(),
348                    aConnector );
349 
350     typedef ::ary::stg::filter_iterator<CodeEntity,Class>
351         filter_class_iter;
352 
353     HierarchyLinker
354         aHierarchyLinker(*this);
355     filter_class_iter itEnd( pCes->Storage().End() );
356     for ( filter_class_iter it( pCes->Storage().BeginUnreserved() );
357           it != itEnd;
358           ++it )
359     {
360         if (NOT it.IsValid())
361             continue;
362 
363         if (is_type<Class>(*it))
364             aHierarchyLinker(ary_cast<Class>(*it));
365     }
366 
367     TypeConnector2ndTry
368         aConnector2ndTry(*this);
369     std::for_each( pTypes->Storage().BeginUnreserved(),
370                    pTypes->Storage().End(),
371                    aConnector2ndTry );
372 }
373 
374 template <class COMPARE>
375 void                    Add2Result(
376                             List_GlobalIds &    o_result,
377                             const SortedIds<COMPARE> &
378                                                 i_data,
379                             const char *        i_begin,
380                             const char *        i_end );
381 template <class COMPARE>
382 void
383 Add2Result( List_GlobalIds &            o_result,
384             const SortedIds<COMPARE> &  i_data,
385             const char *                i_begin,
386             const char *                i_end )
387 {
388     const size_t
389         previous_size   = o_result.size();
390     typename std::vector<typename COMPARE::id_type>::const_iterator
391         it_beg          = i_data.LowerBound(i_begin);
392     typename std::vector<typename COMPARE::id_type>::const_iterator
393         it_end          = i_data.LowerBound(i_end);
394     size_t
395         count_added = static_cast<size_t>( std::distance(it_beg,it_end) );
396     o_result.insert(    o_result.end(),
397                         count_added,
398                         GlobalId() );
399     List_GlobalIds::iterator
400         it_out          = o_result.begin() + previous_size;
401     std::transform(     it_beg, it_end,
402                         it_out,
403                         MakeGlobalId<COMPARE>() );
404 }
405 
406 
407 uintt
408 RepositoryPartition::Get_AlphabeticalList( List_GlobalIds &    o_result,
409                                            const char *        i_begin,
410                                            const char *        i_end ) const
411 {
412     size_t
413         ret = o_result.size();
414 
415     const Ce_Storage &
416         ce_storage = pCes->Storage();
417     const Def_Storage &
418         def_storage = pDefs->Storage();
419 
420     Add2Result( o_result,
421                 ce_storage.TypeIndex(),
422                 i_begin, i_end );
423     Add2Result( o_result,
424                 ce_storage.OperationIndex(),
425                 i_begin, i_end );
426     Add2Result( o_result,
427                 ce_storage.DataIndex(),
428                 i_begin, i_end );
429     Add2Result( o_result,
430                 def_storage.DefineIndex(),
431                 i_begin, i_end );
432     Add2Result( o_result,
433                 def_storage.MacroIndex(),
434                 i_begin, i_end );
435 
436     LesserGlobal
437         aLess(ce_storage, def_storage);
438 
439     std::sort(o_result.begin(), o_result.end(), aLess);
440 
441     return o_result.size() - ret;
442 }
443 
444 
445 
446 
447 }   // namespace cpp
448 }   // namespace ary
449 
450 
451 
452 
453 
454 namespace
455 {
456 
457 
458 void
459 TypeConnector::operator()( Type & io_rType ) const
460 {
461     csv_assert(pGate != 0);
462     UsedType *
463         pt = ::ary::ary_cast<UsedType>(&io_rType);
464     if (pt != 0)
465         pt->Connect2Ce(pGate->Ces());
466 }
467 
468 void
469 TypeConnector2ndTry::operator()( Type & io_rType ) const
470 {
471     csv_assert(pGate != 0);
472     UsedType *
473         pt = ::ary::ary_cast<UsedType>(&io_rType);
474     if (pt != 0)
475         pt->Connect2CeOnlyKnownViaBaseClass(*pGate);
476 }
477 
478 void
479 HierarchyLinker::operator()( Class & io_rCe ) const
480 {
481     csv_assert( ::ary::is_type<Class>(io_rCe) );
482     Class &
483         rClass = io_rCe;
484 
485     for ( List_Bases::const_iterator it = rClass.BaseClasses().begin();
486           it != rClass.BaseClasses().end();
487           ++it )
488     {
489         const CodeEntity *
490             pCe = 0;
491         Type_id
492             nTid = (*it).nId;
493         for ( pCe = pGate->Search_RelatedCe(nTid);
494               ary::ary_cast<Typedef>(pCe) != 0;
495               pCe = pGate->Search_RelatedCe(nTid) )
496         {
497             nTid = static_cast< const Typedef* >(pCe)->DescribingType();
498         }
499         const Class *
500             pClass = ary::ary_cast<Class>(pCe);
501 		if (pClass == 0)
502             return;
503         // KORR_FUTURE:  we need a non const Find_Class()
504         const_cast< Class* >(pClass)->Add_KnownDerivative( io_rCe.CeId() );
505     }
506 }
507 
508 const String &
509 LesserGlobal::NameOf(GlobalId  i_id) const
510 {
511     if ( NOT IsDefine(i_id) )
512     {
513         return rCes[i_id.Id()].LocalName();
514     }
515     else
516     {
517         return rDes[i_id.Id()].LocalName();
518     }
519 }
520 
521 
522 
523 }   // namespace anonymous
524