1
|
/**
|
2
|
* Copyright (C) 2009 EDIT
|
3
|
* European Distributed Institute of Taxonomy
|
4
|
* http://www.e-taxonomy.eu
|
5
|
*
|
6
|
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
7
|
* See LICENSE.TXT at the top of this package for the full license terms.
|
8
|
*/
|
9
|
|
10
|
package eu.etaxonomy.cdm.model.common;
|
11
|
|
12
|
import static org.junit.Assert.assertEquals;
|
13
|
import static org.junit.Assert.assertFalse;
|
14
|
import static org.junit.Assert.assertNotNull;
|
15
|
import static org.junit.Assert.assertNull;
|
16
|
import static org.junit.Assert.assertTrue;
|
17
|
|
18
|
import java.util.Calendar;
|
19
|
|
20
|
import org.apache.log4j.Logger;
|
21
|
import org.joda.time.DateTimeFieldType;
|
22
|
import org.joda.time.MutableDateTime;
|
23
|
import org.joda.time.Partial;
|
24
|
import org.joda.time.ReadableInstant;
|
25
|
import org.junit.Assert;
|
26
|
import org.junit.Before;
|
27
|
import org.junit.Test;
|
28
|
|
29
|
import eu.etaxonomy.cdm.common.UTF8;
|
30
|
import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
|
31
|
|
32
|
/**
|
33
|
* @author a.mueller
|
34
|
*
|
35
|
*/
|
36
|
public class TimePeriodTest {
|
37
|
@SuppressWarnings("unused")
|
38
|
private static final Logger logger = Logger.getLogger(TimePeriodTest.class);
|
39
|
|
40
|
private TimePeriod onlyStartYear;
|
41
|
private TimePeriod onlyEndYear;
|
42
|
private TimePeriod startAndEndYear;
|
43
|
private TimePeriod noStartAndEndYear;
|
44
|
private static final Integer year = 1982;
|
45
|
private static final Integer month = 1;
|
46
|
private static final Integer day = 5;
|
47
|
|
48
|
/**
|
49
|
* @throws java.lang.Exception
|
50
|
*/
|
51
|
@Before
|
52
|
public void setUp() throws Exception {
|
53
|
onlyStartYear = TimePeriod.NewInstance(1922);
|
54
|
onlyEndYear = TimePeriod.NewInstance(null, 1857);;
|
55
|
startAndEndYear = TimePeriod.NewInstance(1931, 1957);
|
56
|
Integer start = null;
|
57
|
Integer end = null;
|
58
|
noStartAndEndYear = TimePeriod.NewInstance(start, end);
|
59
|
}
|
60
|
|
61
|
//************************ TESTS ******************************************
|
62
|
|
63
|
/**
|
64
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance()}.
|
65
|
*/
|
66
|
@Test
|
67
|
public void testNewInstance() {
|
68
|
TimePeriod tp = TimePeriod.NewInstance();
|
69
|
Assert.assertNotNull(tp);
|
70
|
Assert.assertTrue("Timeperiod should be empty",tp.isEmpty());
|
71
|
}
|
72
|
|
73
|
/**
|
74
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(org.joda.time.Partial)}.
|
75
|
*/
|
76
|
@Test
|
77
|
public void testNewInstancePartial() {
|
78
|
TimePeriod tp = TimePeriod.NewInstance(new Partial().with(DateTimeFieldType.dayOfWeek(), 5));
|
79
|
Assert.assertNotNull(tp);
|
80
|
Assert.assertFalse("Timeperiod should not be empty",tp.isEmpty());
|
81
|
}
|
82
|
|
83
|
/**
|
84
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(org.joda.time.Partial, org.joda.time.Partial)}.
|
85
|
*/
|
86
|
@Test
|
87
|
public void testNewInstancePartialPartial() {
|
88
|
TimePeriod tp = TimePeriod.NewInstance(new Partial().with(DateTimeFieldType.dayOfMonth(),day));
|
89
|
Assert.assertNotNull(tp);
|
90
|
Assert.assertFalse("Timeperiod should not be empty",tp.isEmpty());
|
91
|
Assert.assertEquals("Timeperiod's should not be empty", day, tp.getStartDay());
|
92
|
}
|
93
|
|
94
|
/**
|
95
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(java.lang.Integer)}.
|
96
|
*/
|
97
|
@Test
|
98
|
public void testNewInstanceInteger() {
|
99
|
onlyStartYear = TimePeriod.NewInstance(1922);
|
100
|
assertEquals(Integer.valueOf(1922), onlyStartYear.getStartYear());
|
101
|
assertNull(onlyStartYear.getEndYear());
|
102
|
assertEquals("1922", onlyStartYear.getYear());
|
103
|
}
|
104
|
|
105
|
/**
|
106
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(java.lang.Integer, java.lang.Integer)}.
|
107
|
*/
|
108
|
@Test
|
109
|
public void testNewInstanceIntegerInteger() {
|
110
|
startAndEndYear = TimePeriod.NewInstance(1931, 1957);
|
111
|
assertEquals(Integer.valueOf(1957), startAndEndYear.getEndYear());
|
112
|
assertEquals(Integer.valueOf(1931), startAndEndYear.getStartYear());
|
113
|
assertEquals("1931"+TimePeriod.SEP+"1957", startAndEndYear.getYear());
|
114
|
}
|
115
|
|
116
|
/**
|
117
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(java.util.Calendar)}.
|
118
|
*/
|
119
|
@Test
|
120
|
public void testNewInstanceCalendar() {
|
121
|
Calendar cal = Calendar.getInstance();
|
122
|
cal.set(1982, 1, day);
|
123
|
TimePeriod tp = TimePeriod.NewInstance(cal);
|
124
|
Assert.assertNotNull(tp);
|
125
|
Assert.assertFalse("Timeperiod should not be empty",tp.isEmpty());
|
126
|
Assert.assertEquals("Timeperiod's should not be empty", day, tp.getStartDay());
|
127
|
}
|
128
|
|
129
|
/**
|
130
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(java.util.Calendar, java.util.Calendar)}.
|
131
|
*/
|
132
|
@Test
|
133
|
public void testNewInstanceCalendarCalendar() {
|
134
|
Calendar cal = Calendar.getInstance();
|
135
|
cal.set(year, month, day);
|
136
|
Calendar cal2 = Calendar.getInstance();
|
137
|
Integer day2 = 20;
|
138
|
Integer month2 = 7;
|
139
|
Integer year2 = 1985;
|
140
|
cal2.set(year2, month2, day2);
|
141
|
TimePeriod tp = TimePeriod.NewInstance(cal, cal2);
|
142
|
Assert.assertNotNull(tp);
|
143
|
Assert.assertFalse("Timeperiod should not be empty",tp.isEmpty());
|
144
|
Assert.assertEquals("Timeperiod's start should not be equal with cal1", year, tp.getStartYear());
|
145
|
//Calendar starts counting months with 0
|
146
|
Assert.assertEquals("Timeperiod's start should not be equal with cal1 ", (Integer)(month +1), tp.getStartMonth());
|
147
|
Assert.assertEquals("Timeperiod's start should not be equal with cal1", day, tp.getStartDay());
|
148
|
|
149
|
Assert.assertEquals("Timeperiod's start should not be equal with cal2", year2, tp.getEndYear());
|
150
|
//Calendar starts counting months with 0
|
151
|
Assert.assertEquals("Timeperiod's start should not be equal with cal2", (Integer)(month2+1), tp.getEndMonth());
|
152
|
Assert.assertEquals("Timeperiod's end should not be equal with cal2", day2, tp.getEndDay());
|
153
|
}
|
154
|
|
155
|
/**
|
156
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(org.joda.time.ReadableInstant)}.
|
157
|
*/
|
158
|
@Test
|
159
|
public void testNewInstanceReadableInstant() {
|
160
|
ReadableInstant readInst = new MutableDateTime();
|
161
|
TimePeriod tp = TimePeriod.NewInstance(readInst);
|
162
|
Assert.assertNotNull(tp);
|
163
|
Assert.assertFalse("Timeperiod should not be empty",tp.isEmpty());
|
164
|
Assert.assertEquals("Timeperiod's should not be empty", (Integer)readInst.get(DateTimeFieldType.dayOfMonth()), tp.getStartDay());
|
165
|
}
|
166
|
|
167
|
/**
|
168
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#NewInstance(org.joda.time.ReadableInstant, org.joda.time.ReadableInstant)}.
|
169
|
*/
|
170
|
@Test
|
171
|
public void testNewInstanceReadableInstantReadableInstant() {
|
172
|
ReadableInstant readInst = new MutableDateTime();
|
173
|
ReadableInstant readInst2 = new MutableDateTime();
|
174
|
((MutableDateTime)readInst).addDays(5);
|
175
|
TimePeriod tp = TimePeriod.NewInstance(readInst, readInst2);
|
176
|
|
177
|
Assert.assertNotNull(tp);
|
178
|
Assert.assertFalse("Timeperiod should not be empty",tp.isEmpty());
|
179
|
Assert.assertEquals("Timeperiod's day should not be equal to readable instant", (Integer)readInst.get(DateTimeFieldType.dayOfMonth()), tp.getStartDay());
|
180
|
Assert.assertEquals("Timeperiod's day should not be equal to readable instant", (Integer)readInst2.get(DateTimeFieldType.dayOfMonth()), tp.getEndDay());
|
181
|
}
|
182
|
|
183
|
/**
|
184
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#calendarToPartial(java.util.Calendar)}.
|
185
|
*/
|
186
|
@Test
|
187
|
public void testCalendarToPartial() {
|
188
|
Calendar cal = Calendar.getInstance();
|
189
|
cal.set(year, month, day);
|
190
|
Partial part = TimePeriod.calendarToPartial(cal);
|
191
|
Assert.assertEquals("Partial's day should not be equal to calednars day", day, (Integer)part.get(DateTimeFieldType.dayOfMonth()));
|
192
|
}
|
193
|
|
194
|
/**
|
195
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#readableInstantToPartial(org.joda.time.ReadableInstant)}.
|
196
|
*/
|
197
|
@Test
|
198
|
public void testReadableInstantToPartial() {
|
199
|
ReadableInstant readInst = new MutableDateTime();
|
200
|
Partial part = TimePeriod.readableInstantToPartial(readInst);
|
201
|
part.get(DateTimeFieldType.dayOfMonth());
|
202
|
Assert.assertEquals("Partial's day should not be equal to calednars day", (Integer)part.get(DateTimeFieldType.dayOfMonth()), (Integer)part.get(DateTimeFieldType.dayOfMonth()));
|
203
|
}
|
204
|
|
205
|
/**
|
206
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#TimePeriod()}.
|
207
|
*/
|
208
|
@Test
|
209
|
public void testTimePeriod() {
|
210
|
TimePeriod tp = new TimePeriod();
|
211
|
Assert.assertNotNull("Time period must be created",tp);
|
212
|
}
|
213
|
|
214
|
// @Ignore
|
215
|
@Test
|
216
|
public void testSetStart(){
|
217
|
Partial startDate = new Partial().with(DateTimeFieldType.year(), 2010)
|
218
|
.with(DateTimeFieldType.monthOfYear(), 12)
|
219
|
.with(DateTimeFieldType.dayOfMonth(), 16);
|
220
|
Partial newStartDate = new Partial().with(DateTimeFieldType.year(), 1984)
|
221
|
.with(DateTimeFieldType.monthOfYear(), 12)
|
222
|
.with(DateTimeFieldType.dayOfMonth(), 14);
|
223
|
|
224
|
TimePeriod tp = TimePeriod.NewInstance(startDate);
|
225
|
String startString = tp.toString();
|
226
|
assertNull("Freetext should be not set", tp.getFreeText());
|
227
|
tp.setStart(newStartDate);
|
228
|
String changedString = tp.toString();
|
229
|
Assert.assertTrue("Setting the partial should change the string representation of the TimePeriod", !startString.equals(changedString));
|
230
|
|
231
|
//
|
232
|
tp = TimePeriodParser.parseString("1752");
|
233
|
assertNull("Freetext should be not set", tp.getFreeText());
|
234
|
startString = tp.toString();
|
235
|
tp.setStart(newStartDate);
|
236
|
changedString = tp.toString();
|
237
|
Assert.assertTrue("Setting a partial for a parsed time period should change the string representation of the TimePeriod ", !startString.equals(changedString));
|
238
|
|
239
|
//
|
240
|
tp = TimePeriodParser.parseString("any strange date");
|
241
|
assertNotNull("Freetext should be set", tp.getFreeText());
|
242
|
startString = tp.toString();
|
243
|
tp.setStart(newStartDate);
|
244
|
changedString = tp.toString();
|
245
|
Assert.assertEquals("Setting a partial for a time period having the freetext set should not change the string representation of the TimePeriod ", startString, changedString);
|
246
|
|
247
|
|
248
|
//
|
249
|
// tp = TimePeriodParser.parseString("15.12.1730"); //TODO currently not parsed
|
250
|
//
|
251
|
// startString = tp.toString();
|
252
|
// tp.setStart(newStartDate);
|
253
|
// changedString = tp.toString();
|
254
|
//
|
255
|
// Assert.assertTrue("Setting a partial for a parsed time period should change the string representation of the TimePeriod ", !startString.equals(changedString));
|
256
|
}
|
257
|
|
258
|
/**
|
259
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#isPeriod()}.
|
260
|
*/
|
261
|
@Test
|
262
|
public void testIsPeriod() {
|
263
|
assertTrue(startAndEndYear.isPeriod());
|
264
|
assertFalse(onlyStartYear.isPeriod());
|
265
|
assertFalse(onlyEndYear.isPeriod());
|
266
|
assertFalse(noStartAndEndYear.isPeriod());
|
267
|
onlyStartYear.setEndDay(14);
|
268
|
assertFalse(onlyStartYear.isPeriod());
|
269
|
onlyStartYear.setEndYear(1988);
|
270
|
assertTrue(onlyStartYear.isPeriod()); //may be discussed
|
271
|
}
|
272
|
|
273
|
/**
|
274
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#getStart()}.
|
275
|
*/
|
276
|
@Test
|
277
|
public void testGetStart() {
|
278
|
TimePeriod tp = new TimePeriod();
|
279
|
Partial start = new Partial(DateTimeFieldType.year(), 1999);
|
280
|
tp.setStart(start);
|
281
|
Assert.assertEquals("Start year should be 1999", Integer.valueOf(1999), tp.getStartYear());
|
282
|
Assert.assertEquals("Start should be 'start'", start, tp.getStart());
|
283
|
}
|
284
|
|
285
|
|
286
|
/**
|
287
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#getEnd()}.
|
288
|
*/
|
289
|
@Test
|
290
|
public void testGetEnd() {
|
291
|
TimePeriod tp = new TimePeriod();
|
292
|
Partial end = new Partial(DateTimeFieldType.year(), 1999);
|
293
|
tp.setEnd(end);
|
294
|
Assert.assertEquals("End year should be 1999", Integer.valueOf(1999), tp.getEndYear());
|
295
|
Assert.assertEquals("End should be 'end'", end, tp.getEnd());
|
296
|
}
|
297
|
|
298
|
/**
|
299
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#getYear()}.
|
300
|
*/
|
301
|
@Test
|
302
|
public void testGetYear() {
|
303
|
TimePeriod tp = new TimePeriod();
|
304
|
tp.setStartYear(1999);
|
305
|
Assert.assertEquals("Year should be 1999", "1999", tp.getYear());
|
306
|
tp.setEndYear(2002);
|
307
|
Assert.assertEquals("Year should be 1999-2002", "1999"+TimePeriod.SEP+"2002", tp.getYear());
|
308
|
tp.setContinued(true);
|
309
|
Assert.assertEquals("Year should be 1999+", "1999+", tp.getYear());
|
310
|
}
|
311
|
|
312
|
|
313
|
/**
|
314
|
* TODO should be partly moved to a test class for {@link TimePeriodPartialFormatter}
|
315
|
*/
|
316
|
@Test
|
317
|
public void testToStringTimePeriod() {
|
318
|
String endash = UTF8.EN_DASH.toString();
|
319
|
TimePeriod tp1 = TimePeriod.NewInstance(1788,1799);
|
320
|
assertNotNull(tp1);
|
321
|
Assert.assertEquals("1788"+endash+"1799", tp1.toString());
|
322
|
tp1.setStartDay(3);
|
323
|
Assert.assertEquals("1788 MMM 3"+endash+"1799", tp1.toString());
|
324
|
tp1.setEndMonth(11);
|
325
|
Assert.assertEquals("1788 MMM 3"+endash+"1799 Nov", tp1.toString());
|
326
|
tp1.setContinued(true);
|
327
|
Assert.assertEquals("1788 MMM 3+", tp1.toString());
|
328
|
|
329
|
tp1 = TimePeriod.NewInstance(1788,1799);
|
330
|
tp1.setContinued(true);
|
331
|
Assert.assertEquals("1788+", tp1.toString());
|
332
|
tp1 = TimePeriod.NewInstance((Integer)null);
|
333
|
tp1.setContinued(true);
|
334
|
//this is still undefined, could be something like 'xxxx+' in future
|
335
|
Assert.assertEquals("+", tp1.toString());
|
336
|
}
|
337
|
|
338
|
@Test
|
339
|
public void testContinued() {
|
340
|
TimePeriod tp1 = TimePeriod.NewInstance(2017, 2018);
|
341
|
Assert.assertEquals((Integer)2018, tp1.getEndYear());
|
342
|
tp1.setContinued(true);
|
343
|
Assert.assertNull("The end should be removed and also the CONTINUED constant should be returned for getEnd()", tp1.getEnd());
|
344
|
Assert.assertTrue(tp1.isContinued());
|
345
|
Assert.assertEquals(null, tp1.getEndYear());
|
346
|
Assert.assertEquals(null, tp1.getEndMonth());
|
347
|
Assert.assertEquals(null, tp1.getEndDay());
|
348
|
|
349
|
//set continued to false (will not recover old end value)
|
350
|
tp1.setContinued(false);
|
351
|
Assert.assertFalse(tp1.isContinued());
|
352
|
Assert.assertEquals(null, tp1.getEndYear());
|
353
|
Assert.assertEquals(null, tp1.getEndMonth());
|
354
|
Assert.assertEquals(null, tp1.getEndDay());
|
355
|
|
356
|
//replace continued by end
|
357
|
tp1 = TimePeriod.NewInstance(2017, 2018);
|
358
|
tp1.setContinued(true);
|
359
|
Assert.assertTrue(tp1.isContinued());
|
360
|
tp1.setEndMonth(month);
|
361
|
Assert.assertFalse(tp1.isContinued());
|
362
|
Assert.assertEquals(null, tp1.getEndYear());
|
363
|
Assert.assertEquals(month, tp1.getEndMonth());
|
364
|
Assert.assertEquals(null, tp1.getEndDay());
|
365
|
|
366
|
}
|
367
|
|
368
|
|
369
|
|
370
|
/**
|
371
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#clone()}.
|
372
|
*/
|
373
|
@Test
|
374
|
public void testClone() {
|
375
|
Integer startYear = 1788;
|
376
|
Integer startMonth = 6;
|
377
|
Integer startDay = 25;
|
378
|
Integer endDay = 21;
|
379
|
Integer endMonth = 12;
|
380
|
Integer endYear = 1799;
|
381
|
String freeText = "A free period";
|
382
|
TimePeriod tp1 = TimePeriod.NewInstance(startYear,endYear);
|
383
|
tp1.setStartDay(startDay);
|
384
|
tp1.setStartMonth(startMonth);
|
385
|
tp1.setEndDay(endDay);
|
386
|
tp1.setEndMonth(endMonth);
|
387
|
tp1.setFreeText(freeText);
|
388
|
TimePeriod tpClone = (TimePeriod)tp1.clone();
|
389
|
Assert.assertEquals("Start year must be 1788.", startYear, tpClone.getStartYear());
|
390
|
Assert.assertEquals("Start month must be 6.", startMonth, tpClone.getStartMonth());
|
391
|
Assert.assertEquals("Start day must be 25.", startDay, tpClone.getStartDay());
|
392
|
Assert.assertEquals("End year must be 1799.", endYear, tpClone.getEndYear());
|
393
|
Assert.assertEquals("End month must be 12.", endMonth, tpClone.getEndMonth());
|
394
|
Assert.assertEquals("End day must be 21.", endDay, tpClone.getEndDay());
|
395
|
Assert.assertEquals("Cloned time period must be equal to originial", tp1, tpClone);
|
396
|
}
|
397
|
|
398
|
/**
|
399
|
* Test method for {@link eu.etaxonomy.cdm.model.common.TimePeriod#clone()}.
|
400
|
*/
|
401
|
@Test
|
402
|
public void testEquals() {
|
403
|
Integer startYear = 1788;
|
404
|
Integer startMonth = 6;
|
405
|
Integer endDay = 21;
|
406
|
Integer endYear = 1799;
|
407
|
String freeText = "A free period";
|
408
|
|
409
|
TimePeriod tp1 = TimePeriod.NewInstance(startYear);
|
410
|
TimePeriod tpClone = (TimePeriod)tp1.clone();
|
411
|
Assert.assertEquals("Cloned time period must be equal to originial", tp1, tpClone);
|
412
|
|
413
|
tp1.setStartMonth(startMonth);
|
414
|
Assert.assertFalse("Cloned time period must not be equal to originial", tp1.equals(tpClone));
|
415
|
tpClone = (TimePeriod)tp1.clone();
|
416
|
Assert.assertEquals("Cloned time period must be equal to originial", tp1, tpClone);
|
417
|
|
418
|
|
419
|
tp1.setEndYear(endYear);
|
420
|
Assert.assertFalse("Cloned time period must not be equal to originial", tp1.equals(tpClone));
|
421
|
tpClone = (TimePeriod)tp1.clone();
|
422
|
Assert.assertEquals("Cloned time period must be equal to originial", tp1, tpClone);
|
423
|
|
424
|
tp1.setEndDay(endDay);
|
425
|
Assert.assertFalse("Cloned time period must not be equal to originial", tp1.equals(tpClone));
|
426
|
tpClone = (TimePeriod)tp1.clone();
|
427
|
Assert.assertEquals("Cloned time period must be equal to originial", tp1, tpClone);
|
428
|
|
429
|
tp1.setFreeText(freeText);
|
430
|
Assert.assertFalse("Cloned time period must not be equal to originial", tp1.equals(tpClone));
|
431
|
tpClone = (TimePeriod)tp1.clone();
|
432
|
Assert.assertEquals("Cloned time period must be equal to originial", tp1, tpClone);
|
433
|
|
434
|
tp1 = TimePeriod.NewInstance();
|
435
|
Assert.assertFalse("Cloned time period must not be equal to originial", tp1.equals(tpClone));
|
436
|
TimePeriod tp2 = TimePeriod.NewInstance();
|
437
|
Assert.assertEquals("Empty time periods must be equal", tp1, tp2);
|
438
|
|
439
|
tp1.setFreeText(freeText);
|
440
|
Assert.assertFalse("Tp2 must not be equal to originial", tp1.equals(tp2));
|
441
|
tp2.setFreeText("jldskjlfi");
|
442
|
Assert.assertFalse("Tp2 must not be equal to originial", tp1.equals(tpClone));
|
443
|
tp2.setFreeText(freeText);
|
444
|
Assert.assertEquals("Tp2 must be equal", tp1, tp2);
|
445
|
}
|
446
|
|
447
|
|
448
|
|
449
|
}
|