Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
minerva
core
Commits
7808aaa5
Commit
7808aaa5
authored
Mar 22, 2018
by
Piotr Gawron
Browse files
ConfigurationView class removed
parent
f8a7e613
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
frontend-js/testFiles/apiCalls/configuration/token=MOCK_TOKEN_ID&
View file @
7808aaa5
This diff is collapsed.
Click to expand it.
frontend-js/testFiles/apiCalls/projects/drug_target_sample/drugs.search/query=NADH&token=MOCK_TOKEN_ID&
View file @
7808aaa5
This diff is collapsed.
Click to expand it.
frontend-js/testFiles/apiCalls/projects/sample/drugs.search/query=NADH&token=MOCK_TOKEN_ID&
View file @
7808aaa5
This diff is collapsed.
Click to expand it.
model/src/main/java/lcsb/mapviewer/model/user/Configuration.java
deleted
100644 → 0
View file @
f8a7e613
package
lcsb.mapviewer.model.user
;
import
java.io.Serializable
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.GeneratedValue
;
import
javax.persistence.GenerationType
;
import
javax.persistence.Id
;
import
javax.persistence.Table
;
/**
* This class represents one configureable parameter of the system.
*
* @author Piotr Gawron
*
*/
@Entity
@Table
(
name
=
"configuration_table"
)
public
class
Configuration
implements
Serializable
{
/**
*
*/
private
static
final
long
serialVersionUID
=
1L
;
/**
* Unique identifier in the database.
*/
@Id
@GeneratedValue
(
strategy
=
GenerationType
.
IDENTITY
)
@Column
(
name
=
"idDb"
,
unique
=
true
,
nullable
=
false
)
private
int
id
;
/**
* Type of the configuration element.
*/
private
ConfigurationElementType
type
;
/**
* What is the value of the configuration parameter.
*/
private
String
value
;
/**
* @return the id
* @see #id
*/
public
int
getId
()
{
return
id
;
}
/**
* @param id
* the id to set
* @see #id
*/
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
}
/**
* @return the type
* @see #type
*/
public
ConfigurationElementType
getType
()
{
return
type
;
}
/**
* @param type
* the type to set
* @see #type
*/
public
void
setType
(
ConfigurationElementType
type
)
{
this
.
type
=
type
;
}
/**
* @return the value
* @see #value
*/
public
String
getValue
()
{
return
value
;
}
/**
* @param value
* the value to set
* @see #value
*/
public
void
setValue
(
String
value
)
{
this
.
value
=
value
;
}
}
service
/src/main/java/lcsb/mapviewer/
services/view
/Configuration
View
.java
→
model
/src/main/java/lcsb/mapviewer/
model/user
/Configuration
Option
.java
View file @
7808aaa5
package
lcsb.mapviewer.
services.view
;
package
lcsb.mapviewer.
model.user
;
import
java.io.Serializable
;
import
lcsb.mapviewer.model.user.Configuration
;
import
lcsb.mapviewer.model.user.ConfigurationElementType
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.GeneratedValue
;
import
javax.persistence.GenerationType
;
import
javax.persistence.Id
;
import
javax.persistence.Table
;
/**
*
View representation of th
e
C
onfigura
tion element
.
*
This class represents on
e
c
onfigura
ble parameter of the system
.
*
* @author Piotr Gawron
*
* @see Configuration
*
*/
public
class
ConfigurationView
extends
AbstractView
<
Configuration
>
implements
Serializable
{
@Entity
@Table
(
name
=
"configuration_table"
)
public
class
ConfigurationOption
implements
Serializable
{
/**
*
*/
private
static
final
long
serialVersionUID
=
1L
;
/**
* Unique identifier in the database.
*/
@Id
@GeneratedValue
(
strategy
=
GenerationType
.
IDENTITY
)
@Column
(
name
=
"idDb"
,
unique
=
true
,
nullable
=
false
)
private
int
id
;
/**
* Type of the configuration element.
*/
private
ConfigurationElementType
type
;
/**
*
V
alue of the configuration parameter.
*
What is the v
alue of the configuration parameter.
*/
private
String
value
;
private
String
valueType
;
private
String
commonName
;
/**
* Default constructor which creates View for the object given in the parameter.
*
* @param configuration
* object for which we are interested in the view
* @return the id
* @see #id
*/
p
rotected
ConfigurationView
(
Configuration
configuration
)
{
super
(
configuration
)
;
p
ublic
int
getId
(
)
{
return
id
;
}
/**
* Default constructor. Should be used only for deserialization.
* @param id
* the id to set
* @see #id
*/
protected
ConfigurationView
()
{
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
}
/**
...
...
@@ -84,20 +93,4 @@ public class ConfigurationView extends AbstractView<Configuration> implements Se
this
.
value
=
value
;
}
public
String
getValueType
()
{
return
valueType
;
}
public
void
setValueType
(
String
valueType
)
{
this
.
valueType
=
valueType
;
}
public
String
getCommonName
()
{
return
commonName
;
}
public
void
setCommonName
(
String
commonName
)
{
this
.
commonName
=
commonName
;
}
}
model/src/test/java/lcsb/mapviewer/model/user/ConfigurationTest.java
View file @
7808aaa5
...
...
@@ -20,7 +20,7 @@ public class ConfigurationTest {
@Test
public
void
testSerialization
()
{
try
{
SerializationUtils
.
serialize
(
new
Configuration
());
SerializationUtils
.
serialize
(
new
Configuration
Option
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
...
...
@@ -30,7 +30,7 @@ public class ConfigurationTest {
@Test
public
void
testGetters
()
{
try
{
Configuration
conf
=
new
Configuration
();
Configuration
Option
conf
=
new
Configuration
Option
();
int
id
=
81
;
ConfigurationElementType
type
=
ConfigurationElementType
.
DEFAULT_MAP
;
String
value
=
"a.val"
;
...
...
persist/src/main/java/lcsb/mapviewer/persist/dao/ConfigurationDao.java
View file @
7808aaa5
package
lcsb.mapviewer.persist.dao
;
import
lcsb.mapviewer.model.user.Configuration
;
import
lcsb.mapviewer.model.user.Configuration
Option
;
import
lcsb.mapviewer.model.user.ConfigurationElementType
;
/**
...
...
@@ -9,13 +9,13 @@ import lcsb.mapviewer.model.user.ConfigurationElementType;
* @author Piotr Gawron
*
*/
public
class
ConfigurationDao
extends
BaseDao
<
Configuration
>
{
public
class
ConfigurationDao
extends
BaseDao
<
Configuration
Option
>
{
/**
* Default constructor.
*/
public
ConfigurationDao
()
{
super
(
Configuration
.
class
);
super
(
Configuration
Option
.
class
);
}
/**
...
...
@@ -26,7 +26,7 @@ public class ConfigurationDao extends BaseDao<Configuration> {
* type of the parameter that we are interested in
* @return object with configuration value for the type given in the parameter
*/
public
Configuration
getByType
(
ConfigurationElementType
type
)
{
public
Configuration
Option
getByType
(
ConfigurationElementType
type
)
{
return
getByParameter
(
"type"
,
type
);
}
...
...
@@ -38,7 +38,7 @@ public class ConfigurationDao extends BaseDao<Configuration> {
* @return value of the specific configuration parameter
*/
public
String
getValueByType
(
ConfigurationElementType
type
)
{
Configuration
val
=
getByParameter
(
"type"
,
type
);
Configuration
Option
val
=
getByParameter
(
"type"
,
type
);
if
(
val
==
null
)
{
if
(
type
==
null
)
{
return
null
;
...
...
persist/src/main/resources/applicationContext-persist.xml
View file @
7808aaa5
...
...
@@ -87,7 +87,7 @@
<value>
lcsb.mapviewer.model.log.SystemLog
</value>
<value>
lcsb.mapviewer.model.user.BasicPrivilege
</value>
<value>
lcsb.mapviewer.model.user.Configuration
</value>
<value>
lcsb.mapviewer.model.user.Configuration
Option
</value>
<value>
lcsb.mapviewer.model.user.ObjectPrivilege
</value>
<value>
lcsb.mapviewer.model.user.User
</value>
<value>
lcsb.mapviewer.model.user.UserAnnotatorsParam
</value>
...
...
persist/src/test/java/lcsb/mapviewer/persist/dao/ConfigurationDaoTest.java
View file @
7808aaa5
...
...
@@ -8,43 +8,43 @@ import org.junit.Before;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
lcsb.mapviewer.model.user.Configuration
;
import
lcsb.mapviewer.model.user.ConfigurationElementType
;
import
lcsb.mapviewer.model.user.ConfigurationOption
;
import
lcsb.mapviewer.persist.PersistTestFunctions
;
public
class
ConfigurationDaoTest
extends
PersistTestFunctions
{
@Autowired
protected
ConfigurationDao
configurationDao
;
@Autowired
protected
ConfigurationDao
configurationDao
;
@Before
public
void
setUp
()
throws
Exception
{
}
@Before
public
void
setUp
()
throws
Exception
{
}
@After
public
void
tearDown
()
throws
Exception
{
}
@After
public
void
tearDown
()
throws
Exception
{
}
@Test
public
void
testGetNull
()
{
assertNull
(
configurationDao
.
getByType
(
null
));
}
@Test
public
void
testGetNull
()
{
assertNull
(
configurationDao
.
getByType
(
null
));
}
@Test
public
void
testGetValueByType
()
{
// check data for null input (failsafe test)
assertNull
(
configurationDao
.
getValueByType
(
null
));
@Test
public
void
testGetValueByType
()
{
// check data for null input (failsafe test)
assertNull
(
configurationDao
.
getValueByType
(
null
));
// check data for somethig that is in database
String
val
=
configurationDao
.
getValueByType
(
ConfigurationElementType
.
LOGO_TEXT
);
assertNotNull
(
val
);
// check data for somethi
n
g that is in database
String
val
=
configurationDao
.
getValueByType
(
ConfigurationElementType
.
LOGO_TEXT
);
assertNotNull
(
val
);
// remove data from database
Configuration
obj
=
configurationDao
.
getByType
(
ConfigurationElementType
.
LOGO_TEXT
);
configurationDao
.
delete
(
obj
);
// remove data from database
Configuration
Option
obj
=
configurationDao
.
getByType
(
ConfigurationElementType
.
LOGO_TEXT
);
configurationDao
.
delete
(
obj
);
// and now check data for somethig that is not in database
assertNotNull
(
configurationDao
.
getValueByType
(
ConfigurationElementType
.
LOGO_TEXT
));
// and now check data for somethi
n
g that is not in database
assertNotNull
(
configurationDao
.
getValueByType
(
ConfigurationElementType
.
LOGO_TEXT
));
}
}
}
rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationController.java
View file @
7808aaa5
...
...
@@ -23,7 +23,6 @@ import lcsb.mapviewer.api.BaseController;
import
lcsb.mapviewer.common.Configuration
;
import
lcsb.mapviewer.services.SecurityException
;
import
lcsb.mapviewer.services.interfaces.IConfigurationService
;
import
lcsb.mapviewer.services.view.ConfigurationView
;
@RestController
public
class
ConfigurationController
extends
BaseController
{
...
...
@@ -65,14 +64,14 @@ public class ConfigurationController extends BaseController {
@RequestMapping
(
value
=
"/configuration/options/"
,
method
=
{
RequestMethod
.
GET
},
produces
=
{
MediaType
.
APPLICATION_JSON_VALUE
})
public
List
<
ConfigurationView
>
getOptions
(
@CookieValue
(
value
=
Configuration
.
AUTH_TOKEN
)
String
token
)
public
List
<
Map
<
String
,
Object
>
>
getOptions
(
@CookieValue
(
value
=
Configuration
.
AUTH_TOKEN
)
String
token
)
throws
SecurityException
{
return
configurationController
.
getAllValues
(
token
);
}
@RequestMapping
(
value
=
"/configuration/options/{option}"
,
method
=
{
RequestMethod
.
PATCH
},
produces
=
{
MediaType
.
APPLICATION_JSON_VALUE
})
public
ConfigurationView
getOption
(
//
public
Map
<
String
,
Object
>
getOption
(
//
@RequestBody
String
body
,
//
@CookieValue
(
value
=
Configuration
.
AUTH_TOKEN
)
String
token
,
//
@PathVariable
(
value
=
"option"
)
String
option
//
...
...
rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
View file @
7808aaa5
...
...
@@ -29,13 +29,13 @@ import lcsb.mapviewer.model.map.reaction.Reaction;
import
lcsb.mapviewer.model.map.species.Element
;
import
lcsb.mapviewer.model.map.species.field.ModificationState
;
import
lcsb.mapviewer.model.user.ConfigurationElementType
;
import
lcsb.mapviewer.model.user.ConfigurationOption
;
import
lcsb.mapviewer.model.user.PrivilegeType
;
import
lcsb.mapviewer.modelutils.map.ClassTreeNode
;
import
lcsb.mapviewer.modelutils.map.ElementUtils
;
import
lcsb.mapviewer.services.SecurityException
;
import
lcsb.mapviewer.services.interfaces.IConfigurationService
;
import
lcsb.mapviewer.services.utils.data.ColorSchemaType
;
import
lcsb.mapviewer.services.view.ConfigurationView
;
@Transactional
(
value
=
"txManager"
)
public
class
ConfigurationRestImpl
extends
BaseRestImpl
{
...
...
@@ -51,9 +51,23 @@ public class ConfigurationRestImpl extends BaseRestImpl {
@Autowired
private
ModelAnnotator
modelAnnotator
;
public
List
<
ConfigurationView
>
getAllValues
(
String
token
)
throws
SecurityException
{
return
configurationService
.
getAllValues
(
getUserService
().
userHasPrivilege
(
token
,
PrivilegeType
.
CONFIGURATION_MANAGE
));
public
List
<
Map
<
String
,
Object
>>
getAllValues
(
String
token
)
throws
SecurityException
{
List
<
Map
<
String
,
Object
>>
result
=
new
ArrayList
<>();
for
(
ConfigurationOption
option
:
configurationService
.
getAllValues
(
getUserService
().
userHasPrivilege
(
token
,
PrivilegeType
.
CONFIGURATION_MANAGE
)))
{
result
.
add
(
optionToMap
(
option
));
}
return
result
;
}
private
Map
<
String
,
Object
>
optionToMap
(
ConfigurationOption
option
)
{
Map
<
String
,
Object
>
result
=
new
TreeMap
<>();
result
.
put
(
"idObject"
,
option
.
getId
());
result
.
put
(
"type"
,
option
.
getType
());
result
.
put
(
"valueType"
,
option
.
getType
().
getEditType
());
result
.
put
(
"commonName"
,
option
.
getType
().
getCommonName
());
result
.
put
(
"value"
,
option
.
getValue
());
return
result
;
}
/**
...
...
@@ -243,7 +257,7 @@ public class ConfigurationRestImpl extends BaseRestImpl {
return
result
;
}
public
ConfigurationView
updateOption
(
String
token
,
String
option
,
Map
<
String
,
Object
>
data
)
public
Map
<
String
,
Object
>
updateOption
(
String
token
,
String
option
,
Map
<
String
,
Object
>
data
)
throws
SecurityException
{
if
(!
getUserService
().
userHasPrivilege
(
token
,
PrivilegeType
.
CONFIGURATION_MANAGE
))
{
throw
new
SecurityException
(
"Acces denied"
);
...
...
@@ -251,7 +265,7 @@ public class ConfigurationRestImpl extends BaseRestImpl {
ConfigurationElementType
type
=
ConfigurationElementType
.
valueOf
(
option
);
String
value
=
(
String
)
data
.
get
(
"value"
);
configurationService
.
setConfigurationValue
(
type
,
value
);
return
configurationService
.
getValue
(
type
);
return
optionToMap
(
configurationService
.
getValue
(
type
)
)
;
}
public
List
<
Map
<
String
,
Object
>>
getPlugins
(
String
token
,
String
rootPath
)
{
...
...
rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
View file @
7808aaa5
...
...
@@ -19,6 +19,7 @@ import lcsb.mapviewer.common.exception.InvalidArgumentException;
import
lcsb.mapviewer.model.Project
;
import
lcsb.mapviewer.model.map.MiriamType
;
import
lcsb.mapviewer.model.user.BasicPrivilege
;
import
lcsb.mapviewer.model.user.ConfigurationOption
;
import
lcsb.mapviewer.model.user.ObjectPrivilege
;
import
lcsb.mapviewer.model.user.PrivilegeType
;
import
lcsb.mapviewer.model.user.User
;
...
...
@@ -30,7 +31,6 @@ import lcsb.mapviewer.model.user.UserClassValidAnnotations;
import
lcsb.mapviewer.services.SecurityException
;
import
lcsb.mapviewer.services.interfaces.IConfigurationService
;
import
lcsb.mapviewer.services.interfaces.ILayoutService
;
import
lcsb.mapviewer.services.view.ConfigurationView
;
@Transactional
(
value
=
"txManager"
)
public
class
UserRestImpl
extends
BaseRestImpl
{
...
...
@@ -320,7 +320,7 @@ public class UserRestImpl extends BaseRestImpl {
private
Map
<
String
,
Object
>
prepareDefaultObjectPrivilege
(
PrivilegeType
privilegeType
)
{
Map
<
String
,
Object
>
result
=
new
TreeMap
<>();
result
.
put
(
"type"
,
privilegeType
);
Configuration
View
value
=
configurationService
.
getValue
(
privilegeType
);
Configuration
Option
value
=
configurationService
.
getValue
(
privilegeType
);
if
(
value
==
null
)
{
result
.
put
(
"value"
,
0
);
}
else
if
(
value
.
getValue
().
equalsIgnoreCase
(
"true"
))
{
...
...
rest-api/src/test/java/lcsb/mapviewer/api/configuration/ConfigurationRestImplTest.java
View file @
7808aaa5
...
...
@@ -18,7 +18,6 @@ import lcsb.mapviewer.api.RestTestFunctions;
import
lcsb.mapviewer.model.map.MiriamType
;
import
lcsb.mapviewer.model.map.reaction.type.StateTransitionReaction
;
import
lcsb.mapviewer.model.map.species.GenericProtein
;
import
lcsb.mapviewer.services.view.ConfigurationView
;
public
class
ConfigurationRestImplTest
extends
RestTestFunctions
{
...
...
@@ -43,7 +42,7 @@ public class ConfigurationRestImplTest extends RestTestFunctions {
@Test
public
void
testGetAllParams
()
throws
Exception
{
try
{
List
<
ConfigurationView
>
list
=
configurationRestImpl
.
getAllValues
(
token
);
List
<
Map
<
String
,
Object
>
>
list
=
configurationRestImpl
.
getAllValues
(
token
);
assertTrue
(
list
.
size
()
>
0
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
...
...
service/src/main/java/lcsb/mapviewer/services/impl/ConfigurationService.java
View file @
7808aaa5
...
...
@@ -9,13 +9,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.transaction.annotation.Transactional
;
import
lcsb.mapviewer.common.FrameworkVersion
;
import
lcsb.mapviewer.model.user.Configuration
;
import
lcsb.mapviewer.model.user.ConfigurationElementType
;
import
lcsb.mapviewer.model.user.ConfigurationOption
;
import
lcsb.mapviewer.model.user.PrivilegeType
;
import
lcsb.mapviewer.persist.dao.ConfigurationDao
;
import
lcsb.mapviewer.services.interfaces.IConfigurationService
;
import
lcsb.mapviewer.services.view.ConfigurationView
;
import
lcsb.mapviewer.services.view.ConfigurationViewFactory
;
/**
* Service implementation used for accessing and modifying configuration
...
...
@@ -44,17 +42,11 @@ public class ConfigurationService implements IConfigurationService {
@Autowired
private
ConfigurationDao
configurationDao
;
/**
* Factory for {@link ConfigurationView} elements.
*/
@Autowired
private
ConfigurationViewFactory
configurationViewFactory
;
@Override
public
String
getConfigurationValue
(
ConfigurationElementType
type
)
{
Configuration
result
=
configurationDao
.
getByType
(
type
);
Configuration
Option
result
=
configurationDao
.
getByType
(
type
);
if
(
result
==
null
)
{
result
=
new
Configuration
();
result
=
new
Configuration
Option
();
result
.
setType
(
type
);
result
.
setValue
(
type
.
getDefaultValue
());
configurationDao
.
add
(
result
);
...
...
@@ -64,9 +56,9 @@ public class ConfigurationService implements IConfigurationService {
@Override
public
void
setConfigurationValue
(
ConfigurationElementType
type
,
String
value
)
{
Configuration
configuration
=
configurationDao
.
getByType
(
type
);
Configuration
Option
configuration
=
configurationDao
.
getByType
(
type
);
if
(
configuration
==
null
)
{
configuration
=
new
Configuration
();
configuration
=
new
Configuration
Option
();
configuration
.
setType
(
type
);
}
configuration
.
setValue
(
value
);
...
...
@@ -79,36 +71,35 @@ public class ConfigurationService implements IConfigurationService {
}
@Override
public
List
<
Configuration
View
>
getAllValues
(
boolean
includeServerSide
)
{
List
<
Configuration
View
>
result
=
new
ArrayList
<>();
public
List
<
Configuration
Option
>
getAllValues
(
boolean
includeServerSide
)
{
List
<
Configuration
Option
>
result
=
new
ArrayList
<>();
for
(
ConfigurationElementType
type
:
ConfigurationElementType
.
values
())
{
if
(!
type
.
isServerSide
()
||
(
type
.
isServerSide
()
&&
includeServerSide
))
{
Configuration
configuration
=
configurationDao
.
getByType
(
type
);
Configuration
Option
configuration
=
configurationDao
.
getByType
(
type
);
if
(
configuration
==
null
)
{
getConfigurationValue
(
type
);
configuration
=
configurationDao
.
getByType
(
type
);
}
ConfigurationView
element
=
configurationViewFactory
.
create
(
configuration
);
result
.
add
(
element
);
result
.
add
(
configuration
);
}
}
return
result
;
}
@Override
public
Configuration
View
getValue
(
ConfigurationElementType
type
)
{
Configuration
configuration
=
configurationDao
.
getByType
(
type
);
public
Configuration
Option
getValue
(
ConfigurationElementType
type
)
{
Configuration
Option
configuration
=
configurationDao
.
getByType
(
type
);
if
(
configuration
==
null
)
{
getConfigurationValue
(
type
);
configuration
=
configurationDao
.
getByType
(
type
);
}
return
configuration
ViewFactory
.
create
(
configuration
)
;
return
configuration
;
}
@Override
public
void
updateConfiguration
(
List
<
Configuration
View
>
values
)
{
for
(
Configuration
View
configurationElement
:
values
)
{
public
void
updateConfiguration
(
List
<
Configuration
Option
>
values
)
{
for
(
Configuration
Option
configurationElement
:
values
)
{
setConfigurationValue
(
configurationElement
.
getType
(),
configurationElement
.
getValue
());
}
}
...
...
@@ -163,7 +154,7 @@ public class ConfigurationService implements IConfigurationService {
}
@Override
public
Configuration
View
getValue
(
PrivilegeType
type
)
{
public
Configuration
Option
getValue
(
PrivilegeType
type
)
{
String
name
=
"DEFAULT_"
+
type
.
name
();
if
(
EnumUtils
.
isValidEnum
(
ConfigurationElementType
.
class
,
name
))
{
return
getValue
(
ConfigurationElementType
.
valueOf
(
name
));
...
...
service/src/main/java/lcsb/mapviewer/services/interfaces/IConfigurationService.java
View file @
7808aaa5
...
...
@@ -4,115 +4,115 @@ import java.util.List;
import
lcsb.mapviewer.common.FrameworkVersion
;
import
lcsb.mapviewer.model.user.ConfigurationElementType
;
import
lcsb.mapviewer.model.user.ConfigurationOption
;