1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24
25 #include "dependy.hxx"
26 #include <iostream>
27 #include "../support/syshelp.hxx"
28 #include "../support/list.hxx"
29 #include "../xcd/xmltree.hxx"
30 #include "../xcd/parse.hxx"
31
32
33
34 Simstr ShortName(const Simstr & i_rService);
35
36
37
Service(const char * i_sName)38 Service::Service( const char * i_sName )
39 : sName(i_sName)
40 // aImplementations
41 {
42 }
43
44 ServiceInfo &
AddImplementation(const char * i_sLibrary)45 Service::AddImplementation( const char * i_sLibrary )
46 {
47 ServiceInfo * ret = new ServiceInfo(i_sLibrary);
48 aImplementations.push_back(ret);
49 return *ret;
50 }
51
ServiceInfo(const char * i_sLibrary)52 ServiceInfo::ServiceInfo( const char * i_sLibrary )
53 : sImplementingLibrary(i_sLibrary)
54 // aNeededServices
55 {
56 }
57
58 void
AddDependency(const char * i_sNeededService)59 ServiceInfo::AddDependency( const char * i_sNeededService )
60 {
61 aNeededServices.push_back(i_sNeededService);
62 }
63
DependencyFinder()64 DependencyFinder::DependencyFinder()
65 {
66 }
67
~DependencyFinder()68 DependencyFinder::~DependencyFinder()
69 {
70 }
71
72 void
GatherData(const char * i_sSearchDirectory)73 DependencyFinder::GatherData( const char * i_sSearchDirectory )
74 {
75 List<Simstr> aFiles;
76 GatherFileNames( aFiles, i_sSearchDirectory );
77
78 for ( unsigned i = 0; i < aFiles.size(); ++i )
79 {
80 ReadFile( aFiles[i].str() );
81 }
82 }
83
84 void
FindNeededServices(StringVector & o_rLibraries,StringVector & o_rServices,const Simstr & i_rService)85 DependencyFinder::FindNeededServices( StringVector & o_rLibraries,
86 StringVector & o_rServices,
87 const Simstr & i_rService )
88 {
89 Map_Services::const_iterator itService = aServices.find(i_rService);
90 if ( itService == aServices.end() )
91 {
92 std::cerr << "Error: Service \""
93 << i_rService.str()
94 << "\" not found."
95 << std::endl;
96 return ;
97 }
98
99 aResult_Libraries.erase( aResult_Libraries.begin(), aResult_Libraries.end() );
100 aResult_Services.erase( aResult_Services.begin(), aResult_Services.end() );
101
102 // const ServiceInfo & rSInfo = (*itService).second->FirstImplementation();
103 Add2Result( *(*itService).second );
104
105 for ( std::set< Simstr >::const_iterator il = aResult_Libraries.begin();
106 il != aResult_Libraries.end();
107 ++il )
108 {
109 o_rLibraries.push_back(*il);
110 }
111
112 for ( std::set< Simstr >::const_iterator is = aResult_Services.begin();
113 is != aResult_Services.end();
114 ++is )
115 {
116 o_rServices.push_back(*is);
117 }
118 }
119
120 void
ReadFile(const char * i_sFilename)121 DependencyFinder::ReadFile( const char * i_sFilename )
122 {
123 ModuleDescription aModule;
124 X2CParser aParser(aModule);
125
126 if ( !aParser.Parse(i_sFilename) )
127 {
128 std::cerr << "Error: File \""
129 << i_sFilename
130 << "\" could not be parsed."
131 << std::endl;
132 return;
133 }
134
135 // GetResults:
136 Simstr sModule = aModule.ModuleName();
137
138 List < const MultipleTextElement* > aImplServices;
139 List < const MultipleTextElement* > aNeededServices;
140
141 aModule.Get_SupportedServices(aImplServices);
142 aModule.Get_ServiceDependencies(aNeededServices);
143
144 unsigned nImplServicesSize = aImplServices.size();
145 unsigned nNeededServicesSize = aNeededServices.size();
146
147 for ( unsigned i = 0; i < nImplServicesSize; ++i )
148 {
149 const MultipleTextElement & rImpl = *aImplServices[i];
150
151 unsigned nImplDataSize = rImpl.Size();
152 for ( unsigned di = 0; di < nImplDataSize; ++di )
153 {
154 Simstr sService = ShortName(rImpl.Data(di));
155 Service * pService = aServices[sService];
156 if (pService == 0)
157 {
158 pService = new Service(rImpl.Data(di));
159 aServices[sService] = pService;
160 }
161 ServiceInfo & rSInfo = pService->AddImplementation(sModule);
162
163 for ( unsigned n = 0; n < nNeededServicesSize; ++n )
164 {
165 unsigned nNeededDataSize = aNeededServices[n]->Size();
166 for ( unsigned dn = 0; dn < nNeededDataSize; ++dn )
167 {
168 if (! aNeededServices[n]->Data(dn).is_no_text())
169 rSInfo.AddDependency( ShortName(aNeededServices[n]->Data(dn)) );
170 } // end for dn
171 } // end for n
172 } // end for di
173 } // end for i
174 }
175
176 void
Add2Result(const Service & i_rService)177 DependencyFinder::Add2Result( const Service & i_rService )
178 {
179 const ServiceInfo & rSInfo = i_rService.FirstImplementation();
180 aResult_Libraries.insert(rSInfo.Library());
181
182 const ServiceInfo::List_NeededServices & rNeededs
183 = rSInfo.NeededServices();
184 for ( StringVector::const_iterator it = rNeededs.begin();
185 it != rNeededs.end();
186 ++it )
187 {
188 std::pair< std::set< Simstr >::iterator, bool > aInsertResult
189 = aResult_Services.insert(*it);
190 if (aInsertResult.second)
191 { // Needed service not yet known
192 Map_Services::const_iterator itFound = aServices.find(*it);
193 if ( itFound == aServices.end() )
194 {
195 std::cerr << "Needed service \""
196 << (*it).str()
197 << "\" not found,"
198 << std::endl;
199 }
200 else
201 {
202 Add2Result( *(*itFound).second );
203 }
204 } // endif (! aInsertResult.second)
205 } // end for (it)
206 }
207
208
209
210 Simstr
ShortName(const Simstr & i_rService)211 ShortName(const Simstr & i_rService)
212 {
213 const char * pStart = i_rService.str();
214 const char * pEnd = strchr(pStart,' ');
215 if (pEnd != 0)
216 return Simstr(pStart, 0, int(pEnd-pStart));
217 else
218 return i_rService;
219 }
220
221