Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
ecd414c2
Commit
ecd414c2
authored
Mar 22, 2021
by
Matthias Betz
Browse files
tests for TransportationObject and MovedRing
parent
f3a64b8d
Pipeline
#2564
passed with stage
in 2 minutes and 42 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObject.java
View file @
ecd414c2
...
...
@@ -86,6 +86,9 @@ public class TransportationObject extends CityObject {
setMultiSurfaceAccordingToLod
(
ata
,
ms
,
geom
.
getLod
());
break
;
}
}
else
{
throw
new
IllegalStateException
(
"Geometry in TransportationObject cannot be of type "
+
geom
.
getType
()
+
". Only MultiSurface allowed"
);
}
}
for
(
TransportationObject
children
:
composesOf
)
{
...
...
@@ -253,7 +256,7 @@ public class TransportationObject extends CityObject {
public
String
toString
()
{
return
"TransportationObject [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
...
...
@@ -261,7 +264,7 @@ public class TransportationObject extends CityObject {
child
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedRing.java
View file @
ecd414c2
...
...
@@ -78,14 +78,14 @@ public class MovedRing {
double
x
=
Math
.
abs
(
normal
.
getX
());
double
y
=
Math
.
abs
(
normal
.
getY
());
double
z
=
Math
.
abs
(
normal
.
getZ
());
if
(
x
>
y
&&
x
>
z
)
{
if
(
x
>
=
y
&&
x
>
=
z
)
{
for
(
Vector3d
vert
:
vertices
)
{
Vector2d
projCoords
=
new
Vector2d
(
vert
.
getY
(),
vert
.
getZ
());
projectedRing
.
add
(
projCoords
);
}
point
=
new
Vector2d
(
v
.
getY
(),
v
.
getZ
());
}
else
if
(
y
>
x
&&
y
>
z
)
{
}
else
if
(
y
>
=
x
&&
y
>
=
z
)
{
for
(
Vector3d
vert
:
vertices
)
{
Vector2d
projCoords
=
new
Vector2d
(
vert
.
getX
(),
vert
.
getZ
());
projectedRing
.
add
(
projCoords
);
...
...
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObjectTest.java
0 → 100644
View file @
ecd414c2
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
never
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.citygml4j.factory.GMLGeometryFactory
;
import
org.citygml4j.model.citygml.transportation.AuxiliaryTrafficArea
;
import
org.citygml4j.model.citygml.transportation.AuxiliaryTrafficAreaProperty
;
import
org.citygml4j.model.citygml.transportation.Road
;
import
org.citygml4j.model.citygml.transportation.TrafficArea
;
import
org.citygml4j.model.citygml.transportation.TransportationComplex
;
import
org.citygml4j.model.gml.geometry.aggregates.MultiSurfaceProperty
;
import
org.junit.Test
;
import
de.hft.stuttgart.citydoctor2.check.CheckError
;
import
de.hft.stuttgart.citydoctor2.check.CheckId
;
import
de.hft.stuttgart.citydoctor2.check.CheckResult
;
import
de.hft.stuttgart.citydoctor2.check.ResultStatus
;
import
de.hft.stuttgart.citydoctor2.datastructure.TransportationObject.TransportationType
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
public
class
TransportationObjectTest
{
@Test
public
void
testGetFeatureType
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
assertEquals
(
FeatureType
.
TRANSPORTATION
,
to
.
getFeatureType
());
}
@Test
(
expected
=
IllegalStateException
.
class
)
public
void
testReCreateGeometriesSolid
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
SOLID
,
Lod
.
LOD1
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
}
@Test
public
void
testReCreateGeometriesWithComposedOf
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
TransportationComplex
tcMock
=
mock
(
TransportationComplex
.
class
);
to
.
setGmlObject
(
tcMock
);
TransportationObject
ataTo
=
new
TransportationObject
(
TransportationType
.
AUXILLIARY_TRAFFIC_AREA
);
AuxiliaryTrafficArea
ataMock
=
mock
(
AuxiliaryTrafficArea
.
class
);
ataTo
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD2
));
ataTo
.
setGmlObject
(
ataMock
);
tcMock
.
addAuxiliaryTrafficArea
(
new
AuxiliaryTrafficAreaProperty
(
ataMock
));
to
.
addChild
(
ataTo
);
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
tcMock
,
never
()).
setLod1MultiSurface
(
any
());
verify
(
ataMock
).
setLod2MultiSurface
(
any
());
}
@Test
public
void
testReCreateGeometriesMultiSurfaceLod1
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
Road
roadMock
=
mock
(
Road
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD1
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod1MultiSurface
(
any
());
}
@Test
public
void
testReCreateGeometriesMultiSurfaceLod2
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
Road
roadMock
=
mock
(
Road
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD2
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod2MultiSurface
(
any
());
}
@Test
public
void
testReCreateGeometriesMultiSurfaceLod3
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
Road
roadMock
=
mock
(
Road
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD3
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod3MultiSurface
(
any
());
}
@Test
public
void
testReCreateGeometriesMultiSurfaceLod4
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
Road
roadMock
=
mock
(
Road
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD4
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod4MultiSurface
(
any
());
}
@Test
(
expected
=
IllegalStateException
.
class
)
public
void
testReCreateGeometriesMultiSurfaceLod0
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
Road
roadMock
=
mock
(
Road
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD0
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
}
@Test
(
expected
=
IllegalStateException
.
class
)
public
void
testReCreateGeometriesTrafficAreaMultiSurfaceLod1
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TrafficArea
roadMock
=
mock
(
TrafficArea
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD1
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
}
@Test
public
void
testReCreateGeometriesTrafficAreaMultiSurfaceLod2
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TrafficArea
roadMock
=
mock
(
TrafficArea
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD2
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod2MultiSurface
(
any
());
}
@Test
public
void
testReCreateGeometriesTrafficAreaMultiSurfaceLod3
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TrafficArea
roadMock
=
mock
(
TrafficArea
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD3
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod3MultiSurface
(
any
());
}
@Test
public
void
testReCreateGeometriesTrafficAreaMultiSurfaceLod4
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TrafficArea
roadMock
=
mock
(
TrafficArea
.
class
);
to
.
setGmlObject
(
roadMock
);
to
.
addGeometry
(
GeometryTestUtils
.
createDummyGeometry
(
GeometryType
.
MULTI_SURFACE
,
Lod
.
LOD4
));
GMLGeometryFactory
factory
=
new
GMLGeometryFactory
();
to
.
reCreateGeometries
(
factory
,
mock
(
ParserConfiguration
.
class
));
verify
(
roadMock
).
setLod4MultiSurface
(
any
());
}
@Test
public
void
testContainsError
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
to
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
,
ResultStatus
.
ERROR
,
mock
(
CheckError
.
class
)));
assertTrue
(
to
.
containsError
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
));
assertFalse
(
to
.
containsError
(
CheckId
.
C_GE_P_INNER_RINGS_NESTED
));
}
@Test
public
void
testContainsErrorInComposesOf
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TransportationObject
to2
=
new
TransportationObject
(
TransportationType
.
TRACK
);
to
.
addChild
(
to2
);
to2
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
,
ResultStatus
.
ERROR
,
mock
(
CheckError
.
class
)));
assertTrue
(
to
.
containsError
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
));
assertFalse
(
to
.
containsError
(
CheckId
.
C_GE_P_INNER_RINGS_NESTED
));
}
@Test
public
void
testClearAllContainedCheckResults
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TransportationObject
to2
=
mock
(
TransportationObject
.
class
);
to
.
addChild
(
to2
);
assertFalse
(
to
.
containsError
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
));
to
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
,
ResultStatus
.
ERROR
,
mock
(
CheckError
.
class
)));
assertTrue
(
to
.
containsError
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
));
to
.
clearAllContainedCheckResults
();
assertFalse
(
to
.
containsError
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
));
verify
(
to2
).
clearAllContainedCheckResults
();
}
@Test
public
void
testCollectContainedErrors
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TransportationObject
to2
=
mock
(
TransportationObject
.
class
);
to
.
addChild
(
to2
);
to
.
addCheckResult
(
new
CheckResult
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
,
ResultStatus
.
ERROR
,
mock
(
CheckError
.
class
)));
List
<
CheckError
>
errors
=
new
ArrayList
<>();
to
.
collectContainedErrors
(
errors
);
assertEquals
(
1
,
errors
.
size
());
verify
(
to2
).
collectContainedErrors
(
errors
);
}
@Test
public
void
testUnsetGmlGeometriesRoad
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
Road
r
=
mock
(
Road
.
class
);
to
.
setGmlObject
(
r
);
r
.
setLod1MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod2MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod3MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod4MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
to
.
unsetGmlGeometries
();
assertNull
(
r
.
getLod1MultiSurface
());
assertNull
(
r
.
getLod2MultiSurface
());
assertNull
(
r
.
getLod3MultiSurface
());
assertNull
(
r
.
getLod4MultiSurface
());
}
@Test
public
void
testUnsetGmlGeometriesTrafficArea
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
TrafficArea
r
=
mock
(
TrafficArea
.
class
);
to
.
setGmlObject
(
r
);
r
.
setLod2MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod3MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod4MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
to
.
unsetGmlGeometries
();
assertNull
(
r
.
getLod2MultiSurface
());
assertNull
(
r
.
getLod3MultiSurface
());
assertNull
(
r
.
getLod4MultiSurface
());
}
@Test
public
void
testUnsetGmlGeometriesAuxilliaryTrafficArea
()
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
AUXILLIARY_TRAFFIC_AREA
);
AuxiliaryTrafficArea
r
=
mock
(
AuxiliaryTrafficArea
.
class
);
to
.
setGmlObject
(
r
);
r
.
setLod2MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod3MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
r
.
setLod4MultiSurface
(
mock
(
MultiSurfaceProperty
.
class
));
to
.
unsetGmlGeometries
();
assertNull
(
r
.
getLod2MultiSurface
());
assertNull
(
r
.
getLod3MultiSurface
());
assertNull
(
r
.
getLod4MultiSurface
());
}
}
CityDoctorParent/CityDoctorModel/src/test/java/de/hft/stuttgart/citydoctor2/math/MovedRingTest.java
0 → 100644
View file @
ecd414c2
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package
de.hft.stuttgart.citydoctor2.math
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertSame
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
org.junit.Test
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
public
class
MovedRingTest
{
@Test
public
void
testOfRing
()
{
LinearRing
lr
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
10
));
lr
.
addVertex
(
new
Vertex
(
20
,
20
,
20
));
MovedRing
mRing
=
MovedRing
.
ofRing
(
lr
,
new
Vector3d
(
10
,
10
,
10
));
assertEquals
(
new
Vector3d
(
0
,
0
,
0
),
mRing
.
getVertices
().
get
(
0
));
assertEquals
(
new
Vector3d
(
10
,
10
,
10
),
mRing
.
getVertices
().
get
(
1
));
}
@Test
public
void
testGetOriginal
()
{
LinearRing
lr
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
10
));
lr
.
addVertex
(
new
Vertex
(
20
,
20
,
20
));
MovedRing
mRing
=
MovedRing
.
ofRing
(
lr
,
new
Vector3d
(
10
,
10
,
10
));
assertSame
(
lr
,
mRing
.
getOriginal
());
}
@Test
public
void
testIsPointInside1
()
{
LinearRing
lr
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
10
));
lr
.
addVertex
(
new
Vertex
(
20
,
10
,
10
));
lr
.
addVertex
(
new
Vertex
(
20
,
20
,
10
));
lr
.
addVertex
(
new
Vertex
(
10
,
20
,
10
));
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
10
));
MovedRing
mRing
=
MovedRing
.
ofRing
(
lr
,
new
Vector3d
(
10
,
10
,
10
));
assertTrue
(
mRing
.
isPointInside
(
new
Vector3d
(
5
,
5
,
0
)));
assertFalse
(
mRing
.
isPointInside
(
new
Vector3d
(-
0.1
,
5
,
0
)));
assertTrue
(
mRing
.
isPointInside
(
new
Vector3d
(
5
,
0
,
0
)));
assertTrue
(
mRing
.
isPointInside
(
new
Vector3d
(
0
,
0
,
0
)));
}
@Test
public
void
testIsPointInside2
()
{
LinearRing
lr
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
10
));
lr
.
addVertex
(
new
Vertex
(
10
,
20
,
10
));
lr
.
addVertex
(
new
Vertex
(
10
,
20
,
20
));
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
20
));
lr
.
addVertex
(
new
Vertex
(
10
,
10
,
10
));
MovedRing
mRing
=
MovedRing
.
ofRing
(
lr
,
new
Vector3d
(
10
,
10
,
10
));
assertTrue
(
mRing
.
isPointInside
(
new
Vector3d
(
0
,
5
,
5
)));
assertFalse
(
mRing
.
isPointInside
(
new
Vector3d
(
0
,
-
0.1
,
5
)));
assertTrue
(
mRing
.
isPointInside
(
new
Vector3d
(
0
,
5
,
0
)));
assertTrue
(
mRing
.
isPointInside
(
new
Vector3d
(
0
,
0
,
0
)));
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment