Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
OpenWalnut
OpenWalnut Core
Commits
c18f025f
Commit
c18f025f
authored
Sep 14, 2009
by
Alexander Wiebel
Browse files
[ADD
#101
] Made WSubject our top level data structure instead of WDataSet
parent
55e2a327
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
245 additions
and
64 deletions
+245
-64
src/dataHandler/WDataHandler.cpp
src/dataHandler/WDataHandler.cpp
+10
-9
src/dataHandler/WDataHandler.h
src/dataHandler/WDataHandler.h
+13
-11
src/dataHandler/WSubject.cpp
src/dataHandler/WSubject.cpp
+49
-0
src/dataHandler/WSubject.h
src/dataHandler/WSubject.h
+68
-0
src/dataHandler/exceptions/WNoSuchDataSetException.h
src/dataHandler/exceptions/WNoSuchDataSetException.h
+3
-2
src/dataHandler/io/WLoaderBiosig.cpp
src/dataHandler/io/WLoaderBiosig.cpp
+5
-1
src/dataHandler/io/WLoaderEEGASCII.cpp
src/dataHandler/io/WLoaderEEGASCII.cpp
+7
-1
src/dataHandler/io/WLoaderNIfTI.cpp
src/dataHandler/io/WLoaderNIfTI.cpp
+7
-1
src/dataHandler/io/test/WLoaderBiosig_test.h
src/dataHandler/io/test/WLoaderBiosig_test.h
+1
-1
src/dataHandler/io/test/WLoaderEEGASCII_test.h
src/dataHandler/io/test/WLoaderEEGASCII_test.h
+4
-2
src/dataHandler/test/WDataHandler_test.h
src/dataHandler/test/WDataHandler_test.h
+30
-35
src/dataHandler/test/WLoaderManager_test.h
src/dataHandler/test/WLoaderManager_test.h
+3
-1
src/dataHandler/test/WSubject_test.h
src/dataHandler/test/WSubject_test.h
+45
-0
No files found.
src/dataHandler/WDataHandler.cpp
View file @
c18f025f
...
...
@@ -25,7 +25,7 @@
#include <vector>
#include "WDataHandler.h"
#include "W
DataSe
t.h"
#include "W
Subjec
t.h"
#include "exceptions/WNoSuchDataSetException.h"
#include "WLoaderManager.h"
...
...
@@ -34,23 +34,23 @@ WDataHandler::WDataHandler()
}
boost
::
shared_ptr
<
const
W
DataSe
t
>
WDataHandler
::
get
DataSe
t
(
const
unsigned
int
dataSe
tId
)
const
boost
::
shared_ptr
<
const
W
Subjec
t
>
WDataHandler
::
get
Subjec
t
(
const
unsigned
int
subjec
tId
)
const
{
if
(
dataSe
tId
>=
m_
dataSe
ts
.
size
()
)
if
(
subjec
tId
>=
m_
subjec
ts
.
size
()
)
throw
WNoSuchDataSetException
(
"Index too large."
);
return
m_
dataSets
.
at
(
dataSe
tId
);
return
m_
subjects
.
at
(
subjec
tId
);
}
void
WDataHandler
::
add
DataSe
t
(
boost
::
shared_ptr
<
W
DataSe
t
>
new
DataSe
t
)
void
WDataHandler
::
add
Subjec
t
(
boost
::
shared_ptr
<
W
Subjec
t
>
new
Subjec
t
)
{
m_
dataSe
ts
.
push_back
(
new
DataSe
t
);
m_
subjec
ts
.
push_back
(
new
Subjec
t
);
}
unsigned
int
WDataHandler
::
getNumberOf
DataSe
ts
()
const
unsigned
int
WDataHandler
::
getNumberOf
Subjec
ts
()
const
{
return
m_
dataSe
ts
.
size
();
return
m_
subjec
ts
.
size
();
}
...
...
@@ -59,6 +59,7 @@ void WDataHandler::loadDataSets( std::vector< std::string > fileNames )
WLoaderManager
lm
;
for
(
size_t
i
=
0
;
i
<
fileNames
.
size
()
;
++
i
)
{
lm
.
load
(
fileNames
[
i
],
(
boost
::
shared_ptr
<
WDataHandler
>
)
this
);
// TODO( wiebel ): need to associate the dataset to its subject
lm
.
load
(
fileNames
[
i
],
(
boost
::
shared_ptr
<
WDataHandler
>
)
this
);
}
}
src/dataHandler/WDataHandler.h
View file @
c18f025f
...
...
@@ -29,10 +29,12 @@
#include <boost/shared_ptr.hpp>
class
W
DataSe
t
;
class
W
Subjec
t
;
/**
* Provides the environment for storing and accessing DataSets.
* Provides the environment for storing and accessing different subjects.
* As all measured data belongs to one subject, this is the main access point
* to our data.
* \ingroup dataHandler
*/
class
WDataHandler
...
...
@@ -49,20 +51,20 @@ public:
WDataHandler
();
/**
* Get the pointer to the i'th
DataSe
t. The return type is const since we
* want to ensure that each
DataSe
t cannot modified after retrival.
* Get the pointer to the i'th
WSubjec
t. The return type is const since we
* want to ensure that each
subjec
t cannot modified after retrival.
*/
boost
::
shared_ptr
<
const
W
DataSe
t
>
get
DataSe
t
(
const
unsigned
int
dataSe
tId
)
const
;
boost
::
shared_ptr
<
const
W
Subjec
t
>
get
Subjec
t
(
const
unsigned
int
subjec
tId
)
const
;
/**
* Insert a new
DataSe
t referenced by a pointer.
* Insert a new
WSubjec
t referenced by a pointer.
*/
void
add
DataSe
t
(
boost
::
shared_ptr
<
W
DataSe
t
>
new
DataSe
t
);
void
add
Subjec
t
(
boost
::
shared_ptr
<
W
Subjec
t
>
new
Subjec
t
);
/**
* Get the number of
DataSe
ts which are actually handled by our DataHandler.
* Get the number of
subjec
ts which are actually handled by our
W
DataHandler.
*/
unsigned
int
getNumberOf
DataSe
ts
()
const
;
unsigned
int
getNumberOf
Subjec
ts
()
const
;
/**
* Calls WLoaderManager to load the given input file.
...
...
@@ -73,9 +75,9 @@ protected:
private:
/**
* A container for all
DataSe
ts.
* A container for all
WSubjec
ts.
*/
std
::
vector
<
boost
::
shared_ptr
<
W
DataSe
t
>
>
m_
dataSe
ts
;
std
::
vector
<
boost
::
shared_ptr
<
W
Subjec
t
>
>
m_
subjec
ts
;
};
/**
...
...
src/dataHandler/WSubject.cpp
0 → 100644
View file @
c18f025f
//---------------------------------------------------------------------------
//
// Project: OpenWalnut
//
// Copyright 2009 SomeCopyrightowner
//
// This file is part of OpenWalnut.
//
// OpenWalnut 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.
//
// OpenWalnut 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 OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WSubject.h"
#include "exceptions/WNoSuchDataSetException.h"
WSubject
::
WSubject
()
{
}
boost
::
shared_ptr
<
const
WDataSet
>
WSubject
::
getDataSet
(
const
unsigned
int
dataSetId
)
const
{
if
(
dataSetId
>=
m_dataSets
.
size
()
)
throw
WNoSuchDataSetException
(
"Index too large."
);
return
m_dataSets
.
at
(
dataSetId
);
}
void
WSubject
::
addDataSet
(
boost
::
shared_ptr
<
WDataSet
>
newDataSet
)
{
m_dataSets
.
push_back
(
newDataSet
);
}
unsigned
int
WSubject
::
getNumberOfDataSets
()
const
{
return
m_dataSets
.
size
();
}
src/dataHandler/WSubject.h
0 → 100644
View file @
c18f025f
//---------------------------------------------------------------------------
//
// Project: OpenWalnut
//
// Copyright 2009 SomeCopyrightowner
//
// This file is part of OpenWalnut.
//
// OpenWalnut 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.
//
// OpenWalnut 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 OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WSUBJECT_H
#define WSUBJECT_H
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
class
WDataSet
;
/**
* Container for all WDataSets belonging to one subject.
* \ingroup dataHandler
*/
class
WSubject
{
public:
/**
* Empty standard constructor.
*/
WSubject
();
/**
* Get the pointer to the i'th WDataSet. The return type is const since we
* want to ensure that each DataSet cannot modified after retrival.
*/
boost
::
shared_ptr
<
const
WDataSet
>
getDataSet
(
const
unsigned
int
subjectId
)
const
;
/**
* Insert a new DataSet referenced by a pointer.
*/
void
addDataSet
(
boost
::
shared_ptr
<
WDataSet
>
newDataSet
);
/**
* Get the number of DataSets which are actually handled by our subject.
*/
unsigned
int
getNumberOfDataSets
()
const
;
protected:
private:
/**
* A container for all WDataSets belonging to the subject.
*/
std
::
vector
<
boost
::
shared_ptr
<
WDataSet
>
>
m_dataSets
;
};
#endif // WSUBJECT_H
src/dataHandler/exceptions/WNoSuchDataSetException.h
View file @
c18f025f
...
...
@@ -29,8 +29,9 @@
#include "../../common/WException.h"
/**
* Should be thrown when an invalid index is used to get a WDataSet from the
* WDataHandler. An index is invalid if it's greater or equal than the number
* Should be thrown when an invalid index is used to get a WSubject from
* the WDataHandler or a WDataSet from the
* WSubject. An index is invalid if it's greater or equal than the number
* of WDataSets in that WDataHandler.
*
* It's subclassed from std::logic_error since it represents a mistake by a
...
...
src/dataHandler/io/WLoaderBiosig.cpp
View file @
c18f025f
...
...
@@ -33,6 +33,7 @@
#include "../WDataHandler.h"
#include "../WMetaInfo.h"
#include "../WEEG.h"
#include "../WSubject.h"
#include "../../common/WException.h"
WLoaderBiosig
::
WLoaderBiosig
(
std
::
string
fileName
,
boost
::
shared_ptr
<
WDataHandler
>
dataHandler
)
...
...
@@ -127,7 +128,10 @@ void WLoaderBiosig::biosigLoader()
}
boost
::
shared_ptr
<
WEEG
>
eeg
=
boost
::
shared_ptr
<
WEEG
>
(
new
WEEG
(
metaInfo
,
segments
,
lib
,
labels
)
);
m_dataHandler
->
addDataSet
(
eeg
);
boost
::
shared_ptr
<
WSubject
>
subject
;
// TODO( wiebel ): this is a dummy
subject
->
addDataSet
(
eeg
);
m_dataHandler
->
addSubject
(
subject
);
std
::
cout
<<
"BIOSIG loading done."
<<
std
::
endl
;
std
::
cout
<<
"==================================="
<<
std
::
endl
;
...
...
src/dataHandler/io/WLoaderEEGASCII.cpp
View file @
c18f025f
...
...
@@ -28,6 +28,7 @@
#include <boost/lexical_cast.hpp>
#include "WLoaderEEGASCII.h"
#include "../WSubject.h"
#include "../WEEG.h"
#include "../WMetaInfo.h"
#include "../../common/WException.h"
...
...
@@ -84,5 +85,10 @@ void WLoaderEEGASCII::operator()()
WEEGElectrodeLibrary
lib
;
// TODO( wiebel ): this is a dummy
boost
::
shared_ptr
<
WEEG
>
eeg
=
boost
::
shared_ptr
<
WEEG
>
(
new
WEEG
(
metaInfo
,
segments
,
lib
,
labels
)
);
m_dataHandler
->
addDataSet
(
eeg
);
// TODO( wiebel ): this is a dummy
boost
::
shared_ptr
<
WSubject
>
subject
=
boost
::
shared_ptr
<
WSubject
>
(
new
WSubject
);
subject
->
addDataSet
(
eeg
);
m_dataHandler
->
addSubject
(
subject
);
}
src/dataHandler/io/WLoaderNIfTI.cpp
View file @
c18f025f
...
...
@@ -29,6 +29,7 @@
#include "WLoaderNIfTI.h"
#include "../WDataHandler.h"
#include "../WDataSet.h"
#include "../WSubject.h"
#include "../WDataSetSingle.h"
#include "../WGrid.h"
#include "../WGridRegular3D.h"
...
...
@@ -132,7 +133,12 @@ void WLoaderNIfTI::operator()()
boost
::
shared_ptr
<
WDataSet
>
newDataSet
=
boost
::
shared_ptr
<
WDataSet
>
(
new
WDataSetSingle
(
newValueSet
,
newGrid
,
metaInfo
)
);
m_dataHandler
->
addDataSet
(
newDataSet
);
// TODO( wiebel ): this is a dummy
boost
::
shared_ptr
<
WSubject
>
subject
=
boost
::
shared_ptr
<
WSubject
>
(
new
WSubject
);
subject
->
addDataSet
(
newDataSet
);
m_dataHandler
->
addSubject
(
subject
);
}
...
...
src/dataHandler/io/test/WLoaderBiosig_test.h
View file @
c18f025f
...
...
@@ -48,7 +48,7 @@ public:
std
::
cout
<<
std
::
endl
<<
"Test loading of "
<<
fileName
<<
"."
<<
std
::
endl
;
boost
::
shared_ptr
<
WDataHandler
>
dataHandler
=
boost
::
shared_ptr
<
WDataHandler
>
(
new
WDataHandler
()
);
TS_ASSERT_EQUALS
(
dataHandler
->
getNumberOf
DataSe
ts
(),
0
);
TS_ASSERT_EQUALS
(
dataHandler
->
getNumberOf
Subjec
ts
(),
0
);
// WLoaderBiosig biosigLoader( fileName, dataHandler );
// boost::thread loaderThread( biosigLoader );
...
...
src/dataHandler/io/test/WLoaderEEGASCII_test.h
View file @
c18f025f
...
...
@@ -46,12 +46,14 @@ public:
boost
::
shared_ptr
<
WDataHandler
>
dataHandler
=
boost
::
shared_ptr
<
WDataHandler
>
(
new
WDataHandler
()
);
TS_ASSERT_EQUALS
(
dataHandler
->
getNumberOf
DataSe
ts
(),
0
);
TS_ASSERT_EQUALS
(
dataHandler
->
getNumberOf
Subjec
ts
(),
0
);
WLoaderEEGASCII
eegASCIILoader
(
fileName
,
dataHandler
);
boost
::
thread
loaderThread
(
eegASCIILoader
);
sleep
(
3
);
TS_ASSERT_EQUALS
(
dataHandler
->
getNumberOfDataSets
(),
1
);
// TODO( wiebel ): we need to change this because loading, in the end,
// should not always increase the number of subjects.
TS_ASSERT_EQUALS
(
dataHandler
->
getNumberOfSubjects
(),
1
);
}
};
...
...
src/dataHandler/test/WDataHandler_test.h
View file @
c18f025f
...
...
@@ -27,24 +27,21 @@
#include <cxxtest/TestSuite.h>
#include "../WDataHandler.h"
#include "../WDataSet.h"
#include "../WMetaInfo.h"
#include "../WSubject.h"
#include "../exceptions/WNoSuchDataSetException.h"
class
WDataHandlerTest
:
public
CxxTest
::
TestSuite
{
public:
boost
::
shared_ptr
<
W
DataSe
t
>
dummy
DataSe
t
;
boost
::
shared_ptr
<
W
Subjec
t
>
dummy
Subjec
t
;
/**
* Constructs unit test environment.
*/
void
setUp
(
void
)
{
// create a DataSet dummy, since this is needed in almost every test
boost
::
shared_ptr
<
WMetaInfo
>
metaInfo
=
boost
::
shared_ptr
<
WMetaInfo
>
(
new
WMetaInfo
);
dummyDataSet
=
boost
::
shared_ptr
<
WDataSet
>
(
new
WDataSet
(
metaInfo
)
);
// create a subject dummy, since this is needed in almost every test
dummySubject
=
boost
::
shared_ptr
<
WSubject
>
(
new
WSubject
()
);
}
/**
...
...
@@ -62,54 +59,52 @@ public:
void
testAddDataSet
(
void
)
{
WDataHandler
dataHandler
;
TS_ASSERT_EQUALS
(
dataHandler
.
m_
dataSe
ts
.
size
(),
0
);
TS_ASSERT_THROWS_NOTHING
(
dataHandler
.
add
DataSe
t
(
dummy
DataSe
t
)
);
TS_ASSERT_EQUALS
(
dataHandler
.
m_
dataSe
ts
.
size
(),
1
);
TS_ASSERT_EQUALS
(
dataHandler
.
m_
subjec
ts
.
size
(),
0
);
TS_ASSERT_THROWS_NOTHING
(
dataHandler
.
add
Subjec
t
(
dummy
Subjec
t
)
);
TS_ASSERT_EQUALS
(
dataHandler
.
m_
subjec
ts
.
size
(),
1
);
}
/**
* Checks if the size (meaning the number of elements) of our container
* works properly.
*/
void
testGetNumberOf
DataSe
ts
(
void
)
void
testGetNumberOf
Subjec
ts
(
void
)
{
WDataHandler
dataHandler
;
TS_ASSERT_EQUALS
(
dataHandler
.
getNumberOf
DataSe
ts
(),
0
);
dataHandler
.
add
DataSe
t
(
dummy
DataSe
t
);
TS_ASSERT_EQUALS
(
dataHandler
.
getNumberOf
DataSe
ts
(),
1
);
dataHandler
.
add
DataSe
t
(
dummy
DataSe
t
);
TS_ASSERT_EQUALS
(
dataHandler
.
getNumberOf
DataSe
ts
(),
2
);
TS_ASSERT_EQUALS
(
dataHandler
.
getNumberOf
Subjec
ts
(),
0
);
dataHandler
.
add
Subjec
t
(
dummy
Subjec
t
);
TS_ASSERT_EQUALS
(
dataHandler
.
getNumberOf
Subjec
ts
(),
1
);
dataHandler
.
add
Subjec
t
(
dummy
Subjec
t
);
TS_ASSERT_EQUALS
(
dataHandler
.
getNumberOf
Subjec
ts
(),
2
);
}
/**
* When retrieving a
DataSe
t only valid indices are allowed.
* When retrieving a
subjec
t only valid indices are allowed.
*/
void
testGet
DataSe
ts
(
void
)
void
testGet
Subjec
ts
(
void
)
{
WDataHandler
dataHandler
;
boost
::
shared_ptr
<
WMetaInfo
>
metaInfo
=
boost
::
shared_ptr
<
WMetaInfo
>
(
new
WMetaInfo
);
metaInfo
->
setName
(
"Other Data Set"
);
boost
::
shared_ptr
<
WDataSet
>
otherDataSet
=
boost
::
shared_ptr
<
WDataSet
>
(
new
WDataSet
(
metaInfo
)
);
dataHandler
.
addDataSet
(
dummyDataSet
);
dataHandler
.
addDataSet
(
otherDataSet
);
TS_ASSERT_THROWS_NOTHING
(
dataHandler
.
getDataSet
(
0
)
);
TS_ASSERT_THROWS_NOTHING
(
dataHandler
.
getDataSet
(
1
)
);
TS_ASSERT_EQUALS
(
dataHandler
.
getDataSet
(
0
),
dummyDataSet
);
TS_ASSERT_EQUALS
(
dataHandler
.
getDataSet
(
1
),
otherDataSet
);
TS_ASSERT_DIFFERS
(
dataHandler
.
getDataSet
(
1
),
dummyDataSet
);
TS_ASSERT_THROWS
(
dataHandler
.
getDataSet
(
2
),
WNoSuchDataSetException
);
boost
::
shared_ptr
<
WSubject
>
otherSubject
=
boost
::
shared_ptr
<
WSubject
>
(
new
WSubject
);
dataHandler
.
addSubject
(
dummySubject
);
dataHandler
.
addSubject
(
otherSubject
);
TS_ASSERT_THROWS_NOTHING
(
dataHandler
.
getSubject
(
0
)
);
TS_ASSERT_THROWS_NOTHING
(
dataHandler
.
getSubject
(
1
)
);
TS_ASSERT_EQUALS
(
dataHandler
.
getSubject
(
0
),
dummySubject
);
TS_ASSERT_EQUALS
(
dataHandler
.
getSubject
(
1
),
otherSubject
);
TS_ASSERT_DIFFERS
(
dataHandler
.
getSubject
(
1
),
dummySubject
);
TS_ASSERT_THROWS
(
dataHandler
.
getSubject
(
2
),
WNoSuchDataSetException
);
}
/**
* Test prevention of modification of a retrieved
DataSe
t.
* Test prevention of modification of a retrieved
subjec
t.
*/
void
testConstnessOn
DataSe
t
(
void
)
void
testConstnessOn
Subjec
t
(
void
)
{
WDataHandler
dh
;
dh
.
add
DataSe
t
(
dummy
DataSe
t
);
boost
::
shared_ptr
<
const
W
DataSe
t
>
dataSet
=
dh
.
get
DataSe
t
(
0
);
// ToDo(math): I need to try to modify
dataSe
t in order to test
dh
.
add
Subjec
t
(
dummy
Subjec
t
);
boost
::
shared_ptr
<
const
W
Subjec
t
>
dataSet
=
dh
.
get
Subjec
t
(
0
);
// ToDo(math): I need to try to modify
subjec
t in order to test
}
};
...
...
src/dataHandler/test/WLoaderManager_test.h
View file @
c18f025f
...
...
@@ -53,7 +53,9 @@ public:
WLoaderManager
testLoaderManager
;
testLoaderManager
.
load
(
fileName
,
dataHandler
);
sleep
(
4
);
// we need this to allow the thread to terminate
TS_ASSERT
(
dataHandler
->
getNumberOfDataSets
()
);
// TODO( wiebel ): we need to change this because loading, in the end,
// should not always increase the number of subjects.
TS_ASSERT
(
dataHandler
->
getNumberOfSubjects
()
);
}
};
...
...
src/dataHandler/test/WSubject_test.h
0 → 100644
View file @
c18f025f
//---------------------------------------------------------------------------
//
// Project: OpenWalnut
//
// Copyright 2009 SomeCopyrightowner
//
// This file is part of OpenWalnut.
//
// OpenWalnut 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.
//
// OpenWalnut 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 OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WSUBJECT_TEST_H
#define WSUBJECT_TEST_H
#include <cxxtest/TestSuite.h>
#include "../WSubject.h"
/**
* TODO(wiebel): Document this!
*/
class
WSubjectTest
:
public
CxxTest
::
TestSuite
{
public:
/**
* TODO(wiebel): Document this!
*/
void
testSomething
(
void
)
{
}
};
#endif // WSUBJECT_TEST_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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