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 "i2s_calculator.hxx"
30 
31 
32 // NOT FULLY DEFINED SERVICES
33 #include <algorithm>
34 #include <string.h>
35 #include <cosv/file.hxx>
36 //#include <adc_manager.hxx>
37 //#include <adc_options.hxx>
38 #include <ary/qualiname.hxx>
39 #include <ary/idl/i_enum.hxx>
40 #include <ary/idl/i_exception.hxx>
41 #include <ary/idl/i_function.hxx>
42 #include <ary/idl/i_gate.hxx>
43 #include <ary/idl/i_interface.hxx>
44 #include <ary/idl/ik_interface.hxx>
45 #include <ary/idl/i_module.hxx>
46 #include <ary/idl/i_property.hxx>
47 #include <ary/idl/i_service.hxx>
48 #include <ary/idl/i_singleton.hxx>
49 #include <ary/idl/i_siservice.hxx>
50 #include <ary/idl/i_sisingleton.hxx>
51 #include <ary/idl/i_struct.hxx>
52 #include <ary/idl/i_structelem.hxx>
53 #include <ary/idl/i_typedef.hxx>
54 #include <ary/idl/ip_ce.hxx>
55 #include <ary/idl/ip_type.hxx>
56 #include <ary/namesort.hxx>
57 #include <nametreenode.hxx>
58 #include "i_nnfinder.hxx"
59 #include "ia_ce.hxx"
60 #include "ia_type.hxx"
61 #include "is_ce.hxx"
62 #include "is_type.hxx"
63 #include "it_ce.hxx"
64 #include "it_explicit.hxx"
65 #include "it_sequence.hxx"
66 #include "it_xnameroom.hxx"
67 
68 
69 
70 namespace ary
71 {
72 namespace idl
73 {
74 
75 template <class DEST>
76 DEST *
77 SecondariesCalculator::SearchCe4Type(Type_id i_type)
78 {
79     Ce_id
80         ce = lhf_Search_CeFromTypeId(i_type);
81     if (ce.IsValid())
82         return ary_cast<DEST>(& my_CeStorage()[ce]);
83     return 0;
84 }
85 
86 
87 typedef stg::const_iterator<CodeEntity> stg_citerator;
88 typedef stg::iterator<CodeEntity>       stg_iterator;
89 
90 typedef stg::filter_iterator<CodeEntity,Interface>
91                                         interface_iterator;
92 
93 typedef stg::filter_iterator<Type,ExplicitType>
94                                         explicittype_iterator;
95 
96 typedef ary::stg::const_filter_iterator<CodeEntity,Typedef>
97                                         typedef_citerator;
98 
99 
100 inline Service *
101 SecondariesCalculator::lhf_SearchService( Type_id i_nType )
102 {
103     return SearchCe4Type<Service>(i_nType);
104 }
105 
106 inline Interface *
107 SecondariesCalculator::lhf_SearchInterface( Type_id i_nType )
108 {
109     return SearchCe4Type<Interface>(i_nType);
110 }
111 
112 inline Struct *
113 SecondariesCalculator::lhf_SearchStruct( Type_id i_nType )
114 {
115     return SearchCe4Type<Struct>(i_nType);
116 }
117 
118 inline Exception *
119 SecondariesCalculator::lhf_SearchException( Type_id i_nType )
120 {
121     return SearchCe4Type<Exception>(i_nType);
122 }
123 
124 inline const Ce_Storage &
125 SecondariesCalculator::my_CeStorage() const
126 {
127     csv_assert(pCes != 0);
128     return pCes->Storage();
129 }
130 
131 inline const Type_Storage &
132 SecondariesCalculator::my_TypeStorage() const
133 {
134     csv_assert(pTypes != 0);
135     return pTypes->Storage();
136 }
137 
138 inline Ce_Storage &
139 SecondariesCalculator::my_CeStorage()
140 {
141     csv_assert(pCes != 0);
142     return pCes->Storage();
143 }
144 
145 inline Type_Storage &
146 SecondariesCalculator::my_TypeStorage()
147 {
148     csv_assert(pTypes != 0);
149     return pTypes->Storage();
150 }
151 
152 inline void
153 SecondariesCalculator::insert_into2sList( CodeEntity &        o_out,
154                                           int                 i_listIndex,
155                                           Ce_id               i_nCe )
156     { o_out.Secondaries().Access_List(i_listIndex).push_back(i_nCe); }
157 
158 
159 SecondariesCalculator::SecondariesCalculator( CeAdmin &      i_ces,
160                                               TypeAdmin &    i_types )
161     :   pCes(&i_ces),
162         pTypes(&i_types)
163 {
164 }
165 
166 SecondariesCalculator::~SecondariesCalculator()
167 {
168 }
169 
170 
171 void
172 SecondariesCalculator::CheckAllInterfaceBases()
173 {
174     Module &
175         rGlobalNamespace = pCes->GlobalNamespace();
176     QualifiedName
177         aXInterface("::com::sun::star::uno::XInterface","::");
178 
179     const Type &
180         rType = pTypes->CheckIn_Type(   aXInterface,
181                                         0,
182                                         rGlobalNamespace.CeId(),
183                                         0 );
184     Type_id
185         nTypeXInterface = rType.TypeId();
186     const ExplicitType &
187         rExplType = ary_cast<ExplicitType>(rType);
188     Ce_id
189         nCeXInterface = lhf_Search_CeForType(rExplType);
190 
191     interface_iterator itEnd( my_CeStorage().End() );
192     for ( interface_iterator it( my_CeStorage().BeginUnreserved() );
193           it != itEnd;
194           ++it )
195     {
196         if (NOT it.IsValid())
197             continue;
198 
199         Interface &
200             rInterface = *it;
201         if (     NOT rInterface.HasBase()               // According to UNO IDL syntax, an interface without base has com::sun::star::uno::XInterface as base.
202              AND rInterface.CeId() != nCeXInterface )   // XInterface must not be base of itself.
203         {
204             rInterface.Add_Base(nTypeXInterface, 0);
205         }
206     }   // end for
207 }
208 
209 void
210 SecondariesCalculator::Connect_Types2Ces()
211 {
212     explicittype_iterator itEnd( my_TypeStorage().End() );
213     for ( explicittype_iterator it( my_TypeStorage().BeginUnreserved() );
214           it != itEnd;
215           ++it )
216     {
217         if (NOT it.IsValid())
218             continue;
219 
220         ExplicitType &
221             rType = ary_cast<ExplicitType>(*it);
222         Ce_id
223             nRelatedCe = lhf_Search_CeForType(rType);
224         if (nRelatedCe.IsValid())
225         {
226             Ce_Type *
227                 pNew = new Ce_Type(nRelatedCe, rType.TemplateParameters());
228             my_TypeStorage().Replace_Entity( rType.TypeId(),
229                                              *pNew );
230         }
231     }   // end for
232 }
233 
234 void
235 SecondariesCalculator::Gather_CrossReferences()
236 {
237     gather_Synonyms();
238 
239     for ( stg_iterator it = my_CeStorage().Begin();
240           it != my_CeStorage().End();
241           ++it )
242     {
243         (*it).Accept( static_cast< SPInst_asHost& >(*this) );
244 
245     }   // end for
246 
247     sort_All2s();
248 }
249 
250 void
251 SecondariesCalculator::Make_Links2DeveloperManual(
252                                 const String &      i_devman_reffilepath )
253 {
254 //    const autodoc::Options &
255 //        rOptions = TheAutodocManager().TheOptions();
256 //
257 //    const String &
258 //        rDeveloperManual_URL
259 //            = rOptions.Get_Extra(autodoc::OPT_developer_guide);
260 //    const String
261 //        rDeveloperManual_ReferenceFile
262 //            = rOptions.Get_Extra(autodoc::OPT_developer_guide_refs_file);
263 
264 //    if ( rDeveloperManual_URL.length() == 0
265 //         OR
266 //         rDeveloperManual_ReferenceFile.length() == 0 )
267 //    {
268 //        return;
269 //    }
270 
271     csv::File
272         aFile(i_devman_reffilepath, csv::CFM_READ);
273     csv::OpenCloseGuard
274         aFileOpener(aFile);
275     if (aFileOpener)
276     {
277         Read_Links2DevManual(aFile);
278     }
279 }
280 
281 namespace
282 {
283 
284 enum E_LinkMode
285 {
286     link2descr,
287     link2ref
288 };
289 
290 struct OrderCeIdsByName
291 {
292                         OrderCeIdsByName(
293                             const Ce_Storage &      i_storage )
294                                 :   rStorage(i_storage),
295                                     aNameComparison() {}
296     bool                operator()(
297                             Ce_id                   i_ce1,
298                             Ce_id                   i_ce2 ) const
299     {
300         return aNameComparison( rStorage[i_ce1].LocalName(),
301                                 rStorage[i_ce2].LocalName() );
302     }
303 
304   private:
305     const Ce_Storage &  rStorage;
306     LesserName          aNameComparison;
307 };
308 
309 
310 }
311 
312 
313 
314 void
315 SecondariesCalculator::do_Process( const Service & i_rData )
316 {
317     const Service &
318         rService = ary_cast<Service>(i_rData);
319 
320     // Interfaces:
321     assignImplementation_toAServicesInterfaces( rService.CeId(),
322 												rService.CeId(),
323 												interface_2s_ExportingServices );
324     // Services and their interfaces:
325     recursive_AssignIncludingService(rService.CeId(), rService);
326 }
327 
328 void
329 SecondariesCalculator::do_Process( const Interface & i_rData )
330 {
331     assign_AsDerivedInterface( ary_cast<Interface>(i_rData) );
332 }
333 
334 void
335 SecondariesCalculator::do_Process( const Struct &  i_rData )
336 {
337     assign_AsDerivedStruct( ary_cast<Struct>(i_rData) );
338 }
339 
340 void
341 SecondariesCalculator::do_Process( const Exception &  i_rData )
342 {
343     assign_AsDerivedException( ary_cast<Exception>(i_rData) );
344 }
345 
346 void
347 SecondariesCalculator::do_Process( const Typedef &  )
348 {
349     // KORR_FUTURE
350     // Find out what was meant here ???
351 
352 //    const Typedef &
353 //        rTypedef = ary_cast<Typedef>(i_rData);
354 }
355 
356 void
357 SecondariesCalculator::do_Process( const Singleton &  i_rData )
358 {
359     const Singleton &
360         rSingleton = ary_cast<Singleton>(i_rData);
361 
362     Service *
363         pServ = lhf_SearchService(rSingleton.AssociatedService());
364     if (pServ != 0)
365     {
366         insert_into2sUnique( *pServ,
367 							 service_2s_InstantiatingSingletons,
368 							 rSingleton.CeId() );
369     }
370 
371     // Interfaces:
372     assignImplementation_toAServicesInterfaces( rSingleton.CeId(),
373 												lhf_Search_CeFromTypeId(rSingleton.AssociatedService()),
374 												interface_2s_ExportingSingletons );
375 }
376 
377 void
378 SecondariesCalculator::do_Process( const SglIfcService &  i_rData )
379 {
380     const SglIfcService &
381         rSglIfcService = ary_cast<SglIfcService>(i_rData);
382 
383     assignImplementation_toAServicesInterfaces( rSglIfcService.CeId(),
384 												rSglIfcService.CeId(),
385 												interface_2s_ExportingServices );
386 }
387 
388 void
389 SecondariesCalculator::do_Process( const SglIfcSingleton &  i_rData )
390 {
391     const SglIfcSingleton &
392         rSglIfcSingleton = ary_cast<SglIfcSingleton>(i_rData);
393 
394     Type_id nBase = rSglIfcSingleton.BaseInterface();
395     recursive_AssignImplementation_toExportedInterface( rSglIfcSingleton.CeId(),
396 														nBase,
397 														interface_2s_ExportingSingletons );
398 }
399 
400 void
401 SecondariesCalculator::do_Process( const Function & i_rData )
402 {
403     const Function &
404         rFunction = ary_cast<Function>(i_rData);
405 
406     recursive_AssignFunction_toCeAsReturn(rFunction.CeId(), rFunction.ReturnType());
407 
408     for ( Function::ParamList::const_iterator itp = rFunction.Parameters().begin();
409           itp != rFunction.Parameters().end();
410           ++itp )
411     {
412         recursive_AssignFunction_toCeAsParameter(rFunction.CeId(), (*itp).Type());
413     }   // end for (itp)
414 
415     for ( Function::ExceptionList::const_iterator itx = rFunction.Exceptions().begin();
416           itx != rFunction.Exceptions().end();
417           ++itx )
418     {
419         Exception *
420             pX = lhf_SearchException(*itx);
421         if (pX != 0)
422         {
423             insert_into2sUnique(*pX, exception_2s_RaisingFunctions, rFunction.CeId());
424         }
425     }   // end for (itx)
426 }
427 
428 void
429 SecondariesCalculator::do_Process( const StructElement & i_rData )
430 {
431     const StructElement &
432         rStructElement = ary_cast<StructElement>(i_rData);
433 
434     recursive_AssignStructElement_toCeAsDataType(rStructElement.CeId(), rStructElement.Type());
435 }
436 
437 void
438 SecondariesCalculator::do_Process( const Property & i_rData )
439 {
440     const Property &
441         rProperty = ary_cast<Property>(i_rData);
442 
443     recursive_AssignStructElement_toCeAsDataType(rProperty.CeId(), rProperty.Type());
444 }
445 
446 Ce_id
447 SecondariesCalculator::lhf_Search_CeForType( const ExplicitType & i_rType ) const
448 {
449     const ExplicitNameRoom &
450         rExplicitNameRoom = ary_cast<ExplicitNameRoom>(
451                                 my_TypeStorage()[i_rType.NameRoom()] );
452     Find_ModuleNode
453         rNodeFinder( my_CeStorage(),
454                      rExplicitNameRoom.NameChain_Begin(),
455                      rExplicitNameRoom.NameChain_End(),
456                      i_rType.Name() );
457 
458     if ( rExplicitNameRoom.IsAbsolute() )
459     {
460         const Module &
461             rGlobalNamespace = ary_cast<Module>(
462                                 my_CeStorage()[predefined::ce_GlobalNamespace]);
463         return Search_SubTree(  rGlobalNamespace,
464                                 rNodeFinder );
465     }
466     else
467     {
468         const Module &
469             rStartModule = ary_cast<Module>(
470                                 my_CeStorage()[i_rType.ModuleOfOccurrence()]);
471         Ce_id ret = Search_SubTree_UpTillRoot( rStartModule,
472 											   rNodeFinder );
473 		return ret;
474     }   // endif (rExplicitNameRoom.IsAbsolute()) else
475 }
476 
477 Ce_id
478 SecondariesCalculator::lhf_Search_CeFromTypeId( Type_id i_nType ) const
479 {
480     if (NOT i_nType.IsValid())
481         return Ce_id(0);
482     const Ce_Type *
483         pType = ary_cast<Ce_Type>( & my_TypeStorage()[i_nType] );
484     return pType != 0
485                 ?   pType->RelatedCe()
486                 :   Ce_id_Null();
487 }
488 
489 void
490 SecondariesCalculator::assign_CurLink( char *              i_text,
491                                        const String &      i_link,
492                                        const String &      i_linkUI,
493                                        bool                i_isDescr,
494                                        int                 i_lineCount )
495 {
496     csv_assert(i_text != 0);
497 
498     const ary::idl::Module *
499         pModule = & ary_cast<Module>(
500                         my_CeStorage()[predefined::ce_GlobalNamespace]);
501 
502     char * pPastNext = 0;
503     char * pNext = i_text;
504     for ( ;
505           (pPastNext = strstr(pNext,".")) != 0;
506           pNext = pPastNext + 1 )
507     {
508         String sNext(pNext, pPastNext-pNext);
509         Ce_id nModule = pModule->Search_Name(sNext);
510         if (nModule.IsValid())
511         {
512             pModule = ary_cast<Module>( & my_CeStorage()[nModule] );
513         }
514         else
515         {
516             pModule = 0;
517         }
518 
519         if (pModule == 0)
520         {
521             Cerr() << "Warning: Invalid line nr. "
522                    << i_lineCount
523                    << " in DevelopersGuide reference file:\n"
524                    << reinterpret_cast< const char* >(i_text)
525                    << "\n"
526                    << Endl();
527             return;
528         }
529     }   // end for
530 
531     pPastNext = strchr(pNext,':');
532     bool bMember = pPastNext != 0;
533     String sCe( pNext, (bMember ? csv::str::size(pPastNext-pNext) : csv::str::maxsize) );
534 
535 //  KORR_FUTURE
536 //  String sMember(bMember ? pPastNext+1, "");
537 
538     Ce_id nCe = pModule->Search_Name(sCe);
539     if (NOT nCe.IsValid())
540     {
541         Cerr() << "Warning: Invalid line nr. "
542                << i_lineCount
543                << " in DevelopersGuide reference file:\n"
544                << reinterpret_cast< const char* >(i_text)
545                << "\n"
546                << Endl();
547         return;
548     }
549 
550     CodeEntity &
551         rCe = my_CeStorage()[nCe];
552     if (NOT bMember)
553     {
554         if (i_isDescr)
555             rCe.Secondaries().Add_Link2DescriptionInManual(i_link, i_linkUI);
556         else
557             rCe.Secondaries().Add_Link2RefInManual(i_link, i_linkUI);
558         return;
559     }
560     else
561     {
562     // KORR_FUTURE
563     //   Provisorial just doing nothing (or may be
564     //   adding a link at main Ces lists).
565 //    if (i_isDescr)
566 //        rCe.Secondaries().Add_Link2DescriptionInManual(i_link);
567 //    else
568 //        rCe.Secondaries().Add_Link2RefInManual(i_link);
569     }
570 }
571 
572 void
573 SecondariesCalculator::gather_Synonyms()
574 {
575     const Ce_Storage &
576         cstrg = my_CeStorage();
577     typedef_citerator itEnd(cstrg.End());
578     for ( typedef_citerator it(cstrg.Begin());
579           it != itEnd;
580           ++it )
581     {
582         if (NOT it.IsValid())
583             continue;
584 
585         const Typedef &
586             rTypedef = *it;
587         recursive_AssignAsSynonym(rTypedef.CeId(), rTypedef);
588     }   // end for (itTd)
589 }
590 
591 void
592 SecondariesCalculator::recursive_AssignAsSynonym( Ce_id               i_synonymousTypedefsId,
593                                                   const Typedef &     i_TypedefToCheck )
594 {
595     Ce_id
596         nCe = lhf_Search_CeFromTypeId(i_TypedefToCheck.DefiningType());
597     if (NOT nCe.IsValid())
598         return;
599     CodeEntity &
600         rCe = my_CeStorage()[nCe];
601 
602     switch (rCe.AryClass())  // KORR_FUTURE: make this faster, remove switch.
603     {
604         case Interface::class_id:
605                     insert_into2sList( rCe,
606 									   interface_2s_SynonymTypedefs,
607 									   i_synonymousTypedefsId );
608                     break;
609         case Struct::class_id:
610                     insert_into2sList( rCe,
611 									   struct_2s_SynonymTypedefs,
612 									   i_synonymousTypedefsId );
613                     break;
614         case Enum::class_id:
615                     insert_into2sList( rCe,
616 									   enum_2s_SynonymTypedefs,
617 									   i_synonymousTypedefsId );
618                     break;
619         case Typedef::class_id:
620                     insert_into2sList( rCe,
621 									   typedef_2s_SynonymTypedefs,
622 									   i_synonymousTypedefsId );
623                     recursive_AssignAsSynonym( i_synonymousTypedefsId,
624                                                static_cast< Typedef& >(rCe) );
625                     break;
626                 // default: do nothing.
627     }
628 }
629 
630 void
631 SecondariesCalculator::recursive_AssignIncludingService( Ce_id               i_includingServicesId,
632                                                          const Service &     i_ServiceToCheckItsIncludes )
633 {
634     Dyn_StdConstIterator<CommentedRelation>
635         pIncludedServices;
636     i_ServiceToCheckItsIncludes.Get_IncludedServices(pIncludedServices);
637 
638     for ( StdConstIterator<CommentedRelation> &
639                 itServ = *pIncludedServices;
640           itServ;
641           ++itServ )
642     {
643         Service *
644             pServ = lhf_SearchService((*itServ).Type());
645         if (pServ != 0)
646         {
647             insert_into2sUnique( *pServ,
648 								 service_2s_IncludingServices,
649 								 i_includingServicesId
650 							   );
651             recursive_AssignIncludingService(i_includingServicesId, *pServ);
652 
653         }   // end if
654 
655         assignImplementation_toAServicesInterfaces( i_includingServicesId,
656 													lhf_Search_CeFromTypeId( (*itServ).Type() ),
657 													interface_2s_ExportingServices );
658     }   // end for
659 }
660 
661 void
662 SecondariesCalculator::assign_AsDerivedInterface( const Interface & i_rDerived )
663 {
664     ary::Dyn_StdConstIterator<ary::idl::CommentedRelation>
665         pHelp;
666     ary::idl::ifc_interface::attr::Get_Bases(pHelp, i_rDerived);
667 
668     for ( ary::StdConstIterator<ary::idl::CommentedRelation> & it = *pHelp;
669           it.operator bool();
670           ++it )
671     {
672         Interface *
673             pIfc = lhf_SearchInterface( (*it).Type() );
674         if (pIfc == 0)
675             continue;
676 
677         insert_into2sList( *pIfc,
678                            interface_2s_Derivations,
679 						   i_rDerived.CeId() );
680     }   // end for
681 }
682 
683 void
684 SecondariesCalculator::assign_AsDerivedStruct( const Struct &   i_rDerived )
685 {
686     Type_id
687         nBase = i_rDerived.Base();
688     if (nBase.IsValid())
689     {
690         Struct *
691             pParent = lhf_SearchStruct(nBase);
692         if (pParent != 0)
693         {
694             insert_into2sList( *pParent,
695 							   struct_2s_Derivations,
696 							   i_rDerived.CeId() );
697         }
698     }
699 }
700 
701 void
702 SecondariesCalculator::assign_AsDerivedException( const Exception &   i_rDerived )
703 {
704     Type_id
705         nBase = i_rDerived.Base();
706     if (nBase.IsValid())
707     {
708         Exception *
709             pParent = lhf_SearchException(nBase);
710         if (pParent != 0)
711         {
712             insert_into2sList( *pParent,
713 							   exception_2s_Derivations,
714 							   i_rDerived.CeId() );
715         }   // end if
716     }   // end if
717 }
718 
719 void
720 SecondariesCalculator::assignImplementation_toAServicesInterfaces(
721                                                     Ce_id               i_nImpl,
722                                                     Ce_id               i_nService,
723                                                     E_2s_of_Interface   i_eList )
724 {
725     if (NOT i_nService.IsValid())
726         return;
727     Service *
728         pService = ary_cast<Service>( & my_CeStorage()[i_nService] );
729     SglIfcService *
730         pSglIfcService = ary_cast<SglIfcService>( & my_CeStorage()[i_nService] );
731 
732     if (pService != 0)
733     {
734         Dyn_StdConstIterator<CommentedRelation>
735             pSupportedInterfaces;
736         pService->Get_SupportedInterfaces(pSupportedInterfaces);
737 
738         for ( StdConstIterator<CommentedRelation> &
739                     itInfc = *pSupportedInterfaces;
740               itInfc.operator bool();
741 			  ++itInfc )
742         {
743             recursive_AssignImplementation_toExportedInterface( i_nImpl,
744 																(*itInfc).Type(),
745 																i_eList );
746         }   // end for
747     }
748     else if (pSglIfcService != 0)
749     {
750         Type_id nBase = pSglIfcService->BaseInterface();
751         recursive_AssignImplementation_toExportedInterface( i_nImpl,
752 															nBase,
753 															i_eList );
754     }   // end if
755 }
756 
757 void
758 SecondariesCalculator::recursive_AssignImplementation_toExportedInterface(
759                                                     Ce_id               i_nService,
760 													Type_id             i_nExportedInterface,
761 													E_2s_of_Interface   i_eList )
762 {
763     Interface *
764         pIfc = lhf_SearchInterface(i_nExportedInterface);
765     if (pIfc == 0)
766         return;
767 
768     insert_into2sUnique( *pIfc,
769 						 i_eList,
770 						 i_nService );
771     Dyn_StdConstIterator<CommentedRelation>
772         pBases;
773     ary::idl::ifc_interface::attr::Get_Bases(pBases, *pIfc);
774     for ( StdConstIterator<CommentedRelation> & it = *pBases;
775           it.operator bool();
776           ++it )
777     {
778         recursive_AssignImplementation_toExportedInterface(i_nService, (*it).Type(), i_eList);
779     }
780 }
781 
782 void
783 SecondariesCalculator::recursive_AssignFunction_toCeAsReturn( Ce_id         i_nFunction,
784                                                               Type_id       i_nReturnType )
785 {
786     Ce_id
787         nCe = lhf_Search_CeFromTypeId(i_nReturnType);
788     if (NOT nCe.IsValid())
789         return;
790 
791     CodeEntity &
792         rCe = my_CeStorage()[nCe];
793     switch (rCe.AryClass())  // KORR_FUTURE: make this faster, remove switch.
794     {
795         case Interface::class_id:
796                     insert_into2sList( rCe,
797 									   interface_2s_AsReturns,
798 									   i_nFunction );
799                     break;
800         case Struct::class_id:
801                     insert_into2sList( rCe,
802 									   struct_2s_AsReturns,
803 									   i_nFunction );
804                     break;
805         case Enum::class_id:
806                     insert_into2sList( rCe,
807 									   enum_2s_AsReturns,
808 									   i_nFunction );
809                     break;
810         case Typedef::class_id:
811                     insert_into2sList( rCe,
812 									   typedef_2s_AsReturns,
813 									   i_nFunction );
814                     recursive_AssignFunction_toCeAsReturn( i_nFunction,
815                                                            static_cast< Typedef& >(rCe).DefiningType() );
816                     break;
817         // default: do nothing.
818     }
819 }
820 
821 void
822 SecondariesCalculator::recursive_AssignFunction_toCeAsParameter( Ce_id      i_nFunction,
823                                                                  Type_id    i_nParameterType )
824 {
825     Ce_id
826         nCe = lhf_Search_CeFromTypeId(i_nParameterType);
827     if (NOT nCe.IsValid())
828         return;
829 
830     CodeEntity &
831         rCe = my_CeStorage()[nCe];
832     switch (rCe.AryClass())  // KORR_FUTURE: make this faster, remove switch.
833     {
834         case Interface::class_id:
835                     insert_into2sList( rCe,
836 									   interface_2s_AsParameters,
837 									   i_nFunction );
838                     break;
839         case Struct::class_id:
840                     insert_into2sList( rCe,
841 									   struct_2s_AsParameters,
842 									   i_nFunction );
843                     break;
844         case Enum::class_id:
845                     insert_into2sList( rCe,
846 									   enum_2s_AsParameters,
847 									   i_nFunction );
848                     break;
849         case Typedef::class_id:
850                     insert_into2sList( rCe,
851 									   typedef_2s_AsParameters,
852 									   i_nFunction );
853                     recursive_AssignFunction_toCeAsParameter( i_nFunction,
854                                                               static_cast< Typedef& >(rCe).DefiningType() );
855                     break;
856         // default: do nothing.
857     }
858 }
859 
860 void
861 SecondariesCalculator::recursive_AssignStructElement_toCeAsDataType( Ce_id   i_nDataElement,
862                                                                      Type_id i_nDataType )
863 {
864     Ce_id
865         nCe = lhf_Search_CeFromTypeId(i_nDataType);
866     if (NOT nCe.IsValid())
867         return;
868 
869     CodeEntity &
870         rCe = my_CeStorage()[nCe];
871     switch (rCe.AryClass())  // KORR_FUTURE: make this faster, remove switch.
872     {
873         case Interface::class_id:
874                     insert_into2sList( rCe,
875 									   interface_2s_AsDataTypes,
876 									   i_nDataElement );
877                     break;
878         case Struct::class_id:
879                     insert_into2sList( rCe,
880 									   struct_2s_AsDataTypes,
881 									   i_nDataElement );
882                     break;
883         case Enum::class_id:
884                     insert_into2sList( rCe,
885 									   enum_2s_AsDataTypes,
886 									   i_nDataElement );
887                     break;
888         case Typedef::class_id:
889                     insert_into2sList( rCe,
890 									   typedef_2s_AsDataTypes,
891 									   i_nDataElement );
892                     recursive_AssignFunction_toCeAsParameter( i_nDataElement,
893                                                               static_cast< Typedef& >(rCe).DefiningType() );
894                     break;
895         // default: do nothing.
896     }   // end switch
897 }
898 
899 void
900 SecondariesCalculator::insert_into2sUnique( CodeEntity &        o_out,
901 											int                 i_listIndex,
902 											Ce_id               i_nCe )
903 {
904     std::vector<Ce_id> &
905         rOut = o_out.Secondaries().Access_List(i_listIndex);
906     if (std::find(rOut.begin(),rOut.end(),i_nCe) != rOut.end())
907         return;
908     rOut.push_back(i_nCe);
909 }
910 
911 void
912 SecondariesCalculator::sort_All2s()
913 {
914     OrderCeIdsByName
915         aIdOrdering(my_CeStorage());
916 
917     for ( stg_iterator it = my_CeStorage().Begin();
918           it != my_CeStorage().End();
919           ++it )
920     {
921         Ce_2s &
922             r2s = (*it).Secondaries();
923         int iCount = r2s.CountXrefLists();
924         for (int i = 0; i < iCount; ++i)
925         {
926             std::sort( r2s.Access_List(i).begin(),
927                        r2s.Access_List(i).end(),
928                        aIdOrdering );
929         }   // end for (i)
930     }   // end for (it)
931 }
932 
933 void
934 SecondariesCalculator::Read_Links2DevManual( csv::bstream & i_file )
935 {
936     StreamLock  aLine(300);
937     StreamStr & rLine = aLine();
938 
939 
940     String      sCurLink;
941     String      sCurLinkUI;
942     E_LinkMode  eCurMode = link2ref;
943 
944 	int lineCount = 0;
945     const char * sLink = "LINK:";
946     const char * sDescr = "DESCR:";
947     const char * sTopic = "TOPIC:";
948     const char * sRef = "REF:";
949     const UINT8  cMaxASCIINumWhiteSpace = 32;
950 
951     while (NOT i_file.eod())
952     {
953 		++lineCount;
954 
955         rLine.reset();
956         rLine.operator_read_line(i_file);
957 
958         if ( *rLine.c_str() >= 'a' )
959         {
960             assign_CurLink(rLine.begin(), sCurLink, sCurLinkUI, eCurMode == link2descr, lineCount);
961         }
962         else if ( strncmp(rLine.c_str(), sLink, strlen(sLink)) == 0 )
963         {
964             sCurLink = rLine.c_str()+5;
965             sCurLinkUI.clear();
966         }
967         else if ( strncmp(rLine.c_str(), sDescr, strlen(sDescr)) == 0 )
968         {
969             sCurLinkUI = rLine.c_str()+6;
970         }
971         else if ( strncmp(rLine.c_str(), sTopic, strlen(sTopic)) == 0 )
972         {
973             eCurMode = link2descr;
974         }
975         else if ( strncmp(rLine.c_str(), sRef, strlen(sRef)) == 0 )
976         {
977             eCurMode = link2ref;
978         }
979         else if (static_cast<UINT8>(*rLine.c_str()) > cMaxASCIINumWhiteSpace)
980         {
981             assign_CurLink(rLine.begin(), sCurLink, sCurLinkUI, eCurMode == link2descr, lineCount);
982         }
983      // else
984         //  Ignore empty line.
985 
986     }   // end while
987 }
988 
989 
990 
991 }   // namespace idl
992 }   // namespace ary
993