1 package org.apache.maven.archiva.reporting;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.Calendar;
24 import java.util.Date;
25 import java.util.List;
26
27 import org.apache.maven.archiva.database.ArchivaDAO;
28 import org.apache.maven.archiva.database.ArtifactDAO;
29 import org.apache.maven.archiva.database.constraints.ArtifactsByRepositoryConstraint;
30 import org.apache.maven.archiva.model.ArchivaArtifact;
31 import org.apache.maven.archiva.model.RepositoryContentStatistics;
32 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
33 import org.easymock.MockControl;
34 import org.easymock.internal.AlwaysMatcher;
35
36
37
38
39
40
41
42
43 public class SimpleRepositoryStatisticsReportGeneratorTest
44 extends PlexusInSpringTestCase
45 {
46 private MockControl daoControl;
47
48 private ArchivaDAO dao;
49
50 private MockControl artifactDaoControl;
51
52 private ArtifactDAO artifactDao;
53
54 private SimpleRepositoryStatisticsReportGenerator generator;
55
56 private static final String REPO = "test-repo";
57
58 @Override
59 public void setUp()
60 throws Exception
61 {
62 super.setUp();
63
64 daoControl = MockControl.createControl( ArchivaDAO.class );
65 dao = ( ArchivaDAO ) daoControl.getMock();
66
67 generator = new SimpleRepositoryStatisticsReportGenerator();
68 generator.setDao( dao );
69
70 artifactDaoControl = MockControl.createControl( ArtifactDAO.class );
71 artifactDaoControl.setDefaultMatcher( new AlwaysMatcher() );
72 artifactDao = ( ArtifactDAO ) artifactDaoControl.getMock();
73 }
74
75 private Date toDate( int year, int month, int date, int hour, int min, int sec )
76 {
77 Calendar cal = Calendar.getInstance();
78 cal.clear();
79 cal.set( year, month, date, hour, min, sec );
80
81 return cal.getTime();
82 }
83
84 private List<ArchivaArtifact> createArtifacts( String type )
85 {
86 List<ArchivaArtifact> artifacts = new ArrayList<ArchivaArtifact>();
87 artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "1.0", type ) );
88 artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "1.1", type ) );
89 artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "1.2", type ) );
90 artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "2.0", type ) );
91 artifacts.add( createArtifact( REPO, "org.apache.archiva", "repository-statistics-" + type, "3.0", type ) );
92
93 return artifacts;
94 }
95
96 private ArchivaArtifact createArtifact( String repoId, String groupId, String artifactId, String version, String type )
97 {
98 ArchivaArtifact artifact = new ArchivaArtifact( groupId, artifactId, version, null, type, repoId );
99 artifact.getModel().setLastModified( new Date() );
100 return artifact;
101 }
102
103 private RepositoryContentStatistics createRepositoryContentStatistics( Date startDate, String repositoryId )
104 {
105 RepositoryContentStatistics repoContentStats = new RepositoryContentStatistics();
106 repoContentStats.setRepositoryId( repositoryId );
107 repoContentStats.setDuration( 10000 );
108 repoContentStats.setNewFileCount( 100 );
109 repoContentStats.setTotalArtifactCount( 200 );
110 repoContentStats.setTotalFileCount( 250 );
111 repoContentStats.setTotalGroupCount( 100 );
112 repoContentStats.setTotalProjectCount( 180 );
113 repoContentStats.setTotalSize( 200000 );
114 repoContentStats.setWhenGathered( startDate );
115
116 return repoContentStats;
117 }
118
119 private List<RepositoryContentStatistics> createStatisticsHistoryForSingleRepositoryTest( String repoId )
120 {
121 List<RepositoryContentStatistics> repoContentStatsList = new ArrayList<RepositoryContentStatistics>();
122
123 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 11, 1, 0, 0, 0 ), repoId ) );
124 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 10, 16, 0, 0, 0 ), repoId ) );
125 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 10, 1, 0, 0, 0 ), repoId ) );
126 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 9, 16, 0, 0, 0 ), repoId ) );
127 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 9, 1, 0, 0, 0 ), repoId ) );
128 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 8, 16, 0, 0, 0 ), repoId ) );
129 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 8, 1, 0, 0, 0 ), repoId ) );
130 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 7, 16, 0, 0, 0 ), repoId ) );
131 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 7, 1, 0, 0, 0 ), repoId ) );
132 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 6, 16, 0, 0, 0 ), repoId ) );
133 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 6, 1, 0, 0, 0 ), repoId ) );
134 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 5, 16, 0, 0, 0 ), repoId ) );
135 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 5, 1, 0, 0, 0 ), repoId ) );
136 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 4, 16, 0, 0, 0 ), repoId ) );
137 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 4, 1, 0, 0, 0 ), repoId ) );
138 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 3, 16, 0, 0, 0 ), repoId ) );
139 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 3, 1, 0, 0, 0 ), repoId ) );
140 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 2, 16, 0, 0, 0 ), repoId ) );
141 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 2, 1, 0, 0, 0 ), repoId ) );
142 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 1, 16, 0, 0, 0 ), repoId ) );
143 repoContentStatsList.add( createRepositoryContentStatistics( toDate( 2008, 1, 1, 0, 0, 0 ), repoId ) );
144
145 return repoContentStatsList;
146 }
147
148 public void testSimpleReportWithPagination()
149 throws Exception
150 {
151 Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
152 Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
153
154 DataLimits limits = new DataLimits();
155 limits.setPerPageCount( 5 );
156 limits.setCurrentPage( 1 );
157 limits.setCountOfPages( 5 );
158 limits.setTotalCount( 21 );
159
160 List<ArchivaArtifact> jarArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.JAR_TYPE );
161 List<ArchivaArtifact> warArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.WAR_TYPE );
162 List<ArchivaArtifact> mavenPlugins = createArtifacts( RepositoryStatisticsReportGenerator.MAVEN_PLUGIN );
163 List<ArchivaArtifact> exeArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.EXE_TYPE );
164 List<ArchivaArtifact> earArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.EAR_TYPE );
165 List<ArchivaArtifact> dllArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.DLL_TYPE );
166 List<ArchivaArtifact> zipArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.ZIP_TYPE );
167
168 List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
169
170
171 daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
172
173 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
174 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts, 5 );
175
176 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
177 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts, 5 );
178
179 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
180 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins, 5 );
181
182 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
183 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EAR_TYPE, endDate, "whenGathered" ) ), earArtifacts, 5 );
184
185 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
186 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EXE_TYPE, endDate, "whenGathered" ) ), exeArtifacts, 5 );
187
188 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
189 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.DLL_TYPE, endDate, "whenGathered" ) ), dllArtifacts, 5 );
190
191 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
192 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.ZIP_TYPE, endDate, "whenGathered" ) ), zipArtifacts, 5 );
193
194 daoControl.replay();
195 artifactDaoControl.replay();
196
197 List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
198
199 daoControl.verify();
200 artifactDaoControl.verify();
201
202 assertEquals( 5, data.size() );
203
204 RepositoryStatistics stats = (RepositoryStatistics) data.get( 0 );
205 assertEquals( REPO, stats.getRepositoryId() );
206 assertEquals( 200, stats.getArtifactCount() );
207 assertEquals( 5, stats.getJarCount() );
208 assertEquals( 5, stats.getWarCount() );
209 assertEquals( 5, stats.getPluginCount() );
210 assertEquals( 5, stats.getEarCount() );
211 assertEquals( 5, stats.getExeCount() );
212 assertEquals( 5, stats.getDllCount() );
213 assertEquals( 5, stats.getZipCount() );
214 assertEquals( toDate( 2008, 11, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
215 assertEquals( toDate( 2008, 9, 1, 0, 0, 0 ).getTime(), ( (RepositoryStatistics) data.get( 4 ) ).getDateOfScan().getTime() );
216
217
218 limits.setCurrentPage( 5 );
219
220 daoControl.reset();
221 artifactDaoControl.reset();
222
223 artifactDaoControl.setDefaultMatcher( new AlwaysMatcher() );
224
225 daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
226
227 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
228 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts );
229
230 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
231 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts );
232
233 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
234 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins );
235
236 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
237 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EAR_TYPE, endDate, "whenGathered" ) ), earArtifacts );
238
239 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
240 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EXE_TYPE, endDate, "whenGathered" ) ), exeArtifacts );
241
242 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
243 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.DLL_TYPE, endDate, "whenGathered" ) ), dllArtifacts );
244
245 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
246 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.ZIP_TYPE, endDate, "whenGathered" ) ), zipArtifacts );
247
248 daoControl.replay();
249 artifactDaoControl.replay();
250
251 data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
252
253 daoControl.verify();
254 artifactDaoControl.verify();
255
256 assertEquals( 1, data.size() );
257
258 stats = (RepositoryStatistics) data.get( 0 );
259 assertEquals( REPO, stats.getRepositoryId() );
260 assertEquals( 200, stats.getArtifactCount() );
261 assertEquals( 5, stats.getJarCount() );
262 assertEquals( 5, stats.getWarCount() );
263 assertEquals( 5, stats.getPluginCount() );
264 assertEquals( toDate( 2008, 1, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
265 }
266
267 public void testSimpleReportWithoutPagination()
268 throws Exception
269 {
270 Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
271 Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
272
273 List<ArchivaArtifact> jarArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.JAR_TYPE );
274 List<ArchivaArtifact> warArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.WAR_TYPE );
275 List<ArchivaArtifact> mavenPlugins = createArtifacts( RepositoryStatisticsReportGenerator.MAVEN_PLUGIN );
276 List<ArchivaArtifact> exeArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.EXE_TYPE );
277 List<ArchivaArtifact> earArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.EAR_TYPE );
278 List<ArchivaArtifact> dllArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.DLL_TYPE );
279 List<ArchivaArtifact> zipArtifacts = createArtifacts( RepositoryStatisticsReportGenerator.ZIP_TYPE );
280
281 List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
282
283
284 daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
285
286 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
287 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts, 21 );
288
289 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
290 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts, 21 );
291
292 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
293 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins, 21 );
294
295 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
296 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EAR_TYPE, endDate, "whenGathered" ) ), earArtifacts, 21 );
297
298 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
299 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EXE_TYPE, endDate, "whenGathered" ) ), exeArtifacts, 21 );
300
301 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
302 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.DLL_TYPE, endDate, "whenGathered" ) ), dllArtifacts, 21 );
303
304 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
305 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.ZIP_TYPE, endDate, "whenGathered" ) ), zipArtifacts, 21 );
306
307 daoControl.replay();
308 artifactDaoControl.replay();
309
310 List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate, false );
311
312 daoControl.verify();
313 artifactDaoControl.verify();
314
315 assertEquals( 21, data.size() );
316
317 RepositoryStatistics stats = (RepositoryStatistics) data.get( 0 );
318 assertEquals( REPO, stats.getRepositoryId() );
319 assertEquals( 200, stats.getArtifactCount() );
320 assertEquals( 5, stats.getJarCount() );
321 assertEquals( 5, stats.getWarCount() );
322 assertEquals( 5, stats.getPluginCount() );
323 assertEquals( 5, stats.getEarCount() );
324 assertEquals( 5, stats.getExeCount() );
325 assertEquals( 5, stats.getDllCount() );
326 assertEquals( 5, stats.getZipCount() );
327 assertEquals( toDate( 2008, 11, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
328 assertEquals( toDate( 2008, 1, 1, 0, 0, 0 ).getTime(), ( (RepositoryStatistics) data.get( 20 ) ).getDateOfScan().getTime() );
329 }
330
331 public void testSimpleReportNoArtifactCountStatisticsAvailable()
332 throws Exception
333 {
334 Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
335 Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
336
337 DataLimits limits = new DataLimits();
338 limits.setPerPageCount( 5 );
339 limits.setCurrentPage( 1 );
340 limits.setCountOfPages( 5 );
341 limits.setTotalCount( 21 );
342
343 List<ArchivaArtifact> jarArtifacts = new ArrayList<ArchivaArtifact>();
344 List<ArchivaArtifact> warArtifacts = new ArrayList<ArchivaArtifact>();
345 List<ArchivaArtifact> mavenPlugins = new ArrayList<ArchivaArtifact>();
346 List<ArchivaArtifact> earArtifacts = new ArrayList<ArchivaArtifact>();
347 List<ArchivaArtifact> exeArtifacts = new ArrayList<ArchivaArtifact>();
348 List<ArchivaArtifact> dllArtifacts = new ArrayList<ArchivaArtifact>();
349 List<ArchivaArtifact> zipArtifacts = new ArrayList<ArchivaArtifact>();
350
351 List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
352
353 daoControl.expectAndReturn( dao.getArtifactDAO(), artifactDao );
354
355 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
356 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.JAR_TYPE, endDate, "whenGathered") ), jarArtifacts, 5 );
357
358 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
359 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.WAR_TYPE, endDate, "whenGathered") ), warArtifacts, 5 );
360
361 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
362 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.MAVEN_PLUGIN, endDate, "whenGathered") ), mavenPlugins, 5 );
363
364 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
365 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EAR_TYPE, endDate, "whenGathered" ) ), earArtifacts, 5 );
366
367 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
368 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.EXE_TYPE, endDate, "whenGathered" ) ), exeArtifacts, 5 );
369
370 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
371 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.DLL_TYPE, endDate, "whenGathered" ) ), dllArtifacts, 5 );
372
373 artifactDaoControl.expectAndReturn( artifactDao.queryArtifacts(
374 new ArtifactsByRepositoryConstraint( REPO, RepositoryStatisticsReportGenerator.ZIP_TYPE, endDate, "whenGathered" ) ), zipArtifacts, 5 );
375
376 daoControl.replay();
377 artifactDaoControl.replay();
378
379 List<RepositoryStatistics> data = generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
380
381 daoControl.verify();
382 artifactDaoControl.verify();
383
384 assertEquals( 5, data.size() );
385
386 RepositoryStatistics stats = (RepositoryStatistics) data.get( 0 );
387 assertEquals( REPO, stats.getRepositoryId() );
388 assertEquals( 200, stats.getArtifactCount() );
389 assertEquals( 0, stats.getJarCount() );
390 assertEquals( 0, stats.getWarCount() );
391 assertEquals( 0, stats.getPluginCount() );
392 assertEquals( 0, stats.getEarCount() );
393 assertEquals( 0, stats.getExeCount() );
394 assertEquals( 0, stats.getDllCount() );
395 assertEquals( 0, stats.getZipCount() );
396 assertEquals( toDate( 2008, 11, 1, 0, 0, 0 ).getTime(), stats.getDateOfScan().getTime() );
397 assertEquals( toDate( 2008, 9, 1, 0, 0, 0 ).getTime(), ( (RepositoryStatistics) data.get( 4 ) ).getDateOfScan().getTime() );
398
399 }
400
401 public void testSimpleReportWithPaginationInvalidRequestedPage()
402 throws Exception
403 {
404 Date startDate = toDate( 2008, 1, 1, 0, 0, 0 );
405 Date endDate = toDate( 2008, 11, 30, 0, 0, 0 );
406
407 DataLimits limits = new DataLimits();
408 limits.setPerPageCount( 5 );
409 limits.setCurrentPage( 10 );
410 limits.setCountOfPages( 5 );
411 limits.setTotalCount( 21 );
412
413 List<RepositoryContentStatistics> repoContentStats = createStatisticsHistoryForSingleRepositoryTest( REPO );
414
415 try
416 {
417 generator.generateReport( repoContentStats, REPO, startDate, endDate, limits );
418 fail( "An ArchivaReportException should have been thrown." );
419 }
420 catch ( ArchivaReportException a )
421 {
422
423 }
424
425 }
426 }