seeddms-code/SeedDMS_Core/tests/AttributeDefinitionTest.php
2023-01-20 12:28:35 +01:00

575 lines
25 KiB
PHP

<?php
/**
* Implementation of the attribute definiton tests
*
* PHP version 7
*
* @category SeedDMS
* @package Tests
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright 2021 Uwe Steinmann
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @version @package_version@
* @link https://www.seeddms.org
*/
use PHPUnit\Framework\TestCase;
/**
* Attribute definition test class
*
* @category SeedDMS
* @package Tests
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright 2021 Uwe Steinmann
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @version Release: @package_version@
* @link https://www.seeddms.org
*/
class AttributeDefinitionTest extends TestCase
{
/**
* Create a real dms object with a mocked db
*
* This mock is only used if \SeedDMS_Core_DatabaseAccess::getResult() is
* called once. This is the case for all \SeedDMS_Core_AttributeDefinition::setXXX()
* methods like setName().
*
* @return \SeedDMS_Core_DMS
*/
protected function getDmsWithMockedDb() : \SeedDMS_Core_DMS
{
$db = $this->createMock(\SeedDMS_Core_DatabaseAccess::class);
$db->expects($this->once())
->method('getResult')
->with($this->stringContains("UPDATE "))
->willReturn(true);
$dms = new \SeedDMS_Core_DMS($db, '');
return $dms;
}
/**
* Create a mocked dms
*
* @return \SeedDMS_Core_DMS
*/
protected function getDmsMock() : \SeedDMS_Core_DMS
{
$dms = $this->createMock(\SeedDMS_Core_DMS::class);
$dms->expects($this->any())
->method('getDocument')
->with(1)
->willReturn(true);
$dms->expects($this->any())
->method('getFolder')
->with(1)
->willReturn(true);
$dms->expects($this->any())
->method('getUser')
->will(
$this->returnValueMap(
array(
array(1, new \SeedDMS_Core_User(1, 'admin', 'pass', 'Joe Foo', 'baz@foo.de', 'en_GB', 'bootstrap', 'My comment', \SeedDMS_Core_User::role_admin)),
array(2, new \SeedDMS_Core_User(2, 'admin2', 'pass', 'Joe Bar', 'bar@foo.de', 'en_GB', 'bootstrap', 'My comment', \SeedDMS_Core_User::role_admin)),
array(3, null)
)
)
);
$dms->expects($this->any())
->method('getGroup')
->will(
$this->returnValueMap(
array(
array(1, new \SeedDMS_Core_Group(1, 'admin group 1', 'My comment')),
array(2, new \SeedDMS_Core_Group(2, 'admin group 2', 'My comment')),
array(3, null)
)
)
);
return $dms;
}
/**
* Create a mock attribute definition object
*
* @param int $type type of attribute
* @param boolean $multiple set to true for multi value attributes
* @param int $minvalues minimum number of attribute values
* @param int $maxvalues maximum number of attribute values
* @param string $valueset list of allowed values separated by the first char
* @param string $regex regular expression that must match the attribute value
*
* @return \SeedDMS_Core_AttributeDefinition
*/
protected function getAttributeDefinition($type, $multiple=false, $minvalues=0, $maxvalues=0, $valueset='', $regex='')
{
$attrdef = new \SeedDMS_Core_AttributeDefinition(1, 'foo attr', \SeedDMS_Core_AttributeDefinition::objtype_folder, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex);
return $attrdef;
}
/**
* Test getId()
*
* @return void
*/
public function testGetId()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals(1, $attrdef->getId());
}
/**
* Test getName()
*
* @return void
*/
public function testGetName()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals('foo attr', $attrdef->getName());
}
/**
* Test setName()
*
* @return void
*/
public function testSetName()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
$attrdef->setName('bar attr');
$this->assertEquals('bar attr', $attrdef->getName());
}
/**
* Test getObjType()
*
* @return void
*/
public function testGetObjType()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::objtype_folder, $attrdef->getObjType());
}
/**
* Test setObjType()
*
* @return void
*/
public function testSetObjType()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
$attrdef->setObjType(\SeedDMS_Core_AttributeDefinition::objtype_document);
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::objtype_document, $attrdef->getObjType());
}
/**
* Test getType()
*
* @return void
*/
public function testGetType()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::type_int, $attrdef->getType());
}
/**
* Test setType()
*
* @return void
*/
public function testSetType()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
$attrdef->setType(\SeedDMS_Core_AttributeDefinition::type_string);
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::type_string, $attrdef->getType());
}
/**
* Test getMultipleValues()
*
* @return void
*/
public function testGetMultipleValues()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals(false, $attrdef->getMultipleValues());
}
/**
* Test setMultipleValues()
*
* @return void
*/
public function testSetMultipleValues()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
/* Toogle the current value of multiple values */
$oldvalue = $attrdef->getMultipleValues();
$attrdef->setMultipleValues(!$oldvalue);
$this->assertEquals(!$oldvalue, $attrdef->getMultipleValues());
}
/**
* Test getMinValues()
*
* @return void
*/
public function testGetMinValues()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals(0, $attrdef->getMinValues());
}
/**
* Test setMinValues()
*
* @return void
*/
public function testSetMinValues()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
/* add 5 to value of min values */
$oldvalue = $attrdef->getMinValues();
$attrdef->setMinValues($oldvalue+5);
$this->assertEquals($oldvalue+5, $attrdef->getMinValues());
}
/**
* Test getMaxValues()
*
* @return void
*/
public function testGetMaxValues()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEquals(0, $attrdef->getMaxValues());
}
/**
* Test setMaxValues()
*
* @return void
*/
public function testSetMaxValues()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
/* add 5 to value of max values */
$oldvalue = $attrdef->getMaxValues();
$attrdef->setMaxValues($oldvalue+5);
$this->assertEquals($oldvalue+5, $attrdef->getMaxValues());
}
/**
* Test getValueSet()
*
* @return void
*/
public function testGetValueSet()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz');
$this->assertEquals('|foo|bar|baz', $attrdef->getValueSet());
}
/**
* Test getValueSetSeparator()
*
* @return void
*/
public function testGetValueSetSeparator()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz');
$this->assertEquals('|', $attrdef->getValueSetSeparator());
/* No value set will return no separator */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertEmpty($attrdef->getValueSetSeparator());
/* Even a 1 char value set will return no separator */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|');
$this->assertEmpty($attrdef->getValueSetSeparator());
/* Multiple users or groups always use a ',' as a separator */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user, true);
$this->assertEquals(',', $attrdef->getValueSetSeparator());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_group, true);
$this->assertEquals(',', $attrdef->getValueSetSeparator());
}
/**
* Test getValueSetAsArray()
*
* @return void
*/
public function testGetValueSetAsArray()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz ');
$valueset = $attrdef->getValueSetAsArray();
$this->assertIsArray($valueset);
$this->assertCount(3, $valueset);
/* value set must contain 'baz' though 'baz ' was originally set */
$this->assertContains('baz', $valueset);
/* No value set will return an empty array */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string);
$valueset = $attrdef->getValueSetAsArray();
$this->assertIsArray($valueset);
$this->assertEmpty($valueset);
}
/**
* Test getValueSetValue()
*
* @return void
*/
public function testGetValueSetValue()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz ');
$this->assertEquals('foo', $attrdef->getValueSetValue(0));
/* Check if trimming of 'baz ' worked */
$this->assertEquals('baz', $attrdef->getValueSetValue(2));
/* Getting the value of a none existing index returns false */
$this->assertFalse($attrdef->getValueSetValue(3));
/* Getting a value from a none existing value set returns false as well */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string);
$this->assertFalse($attrdef->getValueSetValue(0));
}
/**
* Test setValueSet()
*
* @return void
*/
public function testSetValueSet()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
/* add 5 to value of min values */
$attrdef->setValueSet(' |foo|bar | baz ');
$this->assertEquals('|foo|bar|baz', $attrdef->getValueSet());
}
/**
* Test getRegex()
*
* @return void
*/
public function testGetRegex()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '', '[0-9].*');
$this->assertEquals('[0-9].*', $attrdef->getRegex());
}
/**
* Test setRegex()
*
* @return void
*/
public function testSetRegex()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
/* set a new valid regex */
$this->assertTrue($attrdef->setRegex(' /[0-9].*/i '));
$this->assertEquals('/[0-9].*/i', $attrdef->getRegex());
/* set a new invalid regex will return false and keep the old regex */
$this->assertFalse($attrdef->setRegex(' /([0-9].*/i '));
$this->assertEquals('/[0-9].*/i', $attrdef->getRegex());
}
/**
* Test setEmptyRegex()
*
* @return void
*/
public function testSetEmptyRegex()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string);
/* A mocked dms is needed for updating the database */
$attrdef->setDMS(self::getDmsWithMockedDb());
/* set an empty regex */
$this->assertTrue($attrdef->setRegex(''));
}
/**
* Test parseValue()
*
* @return void
*/
public function testParseValue()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string);
$value = $attrdef->parseValue('foo');
$this->assertIsArray($value);
$this->assertCount(1, $value);
$this->assertContains('foo', $value);
/* An attribute definition with multiple values will split the value by the first char */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, true, 0, 0, '|baz|bar|foo');
$value = $attrdef->parseValue('|bar|baz');
$this->assertIsArray($value);
$this->assertCount(2, $value);
/* An attribute definition without multiple values, will treat the value as a string */
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|baz|bar|foo');
$value = $attrdef->parseValue('|bar|baz');
$this->assertIsArray($value);
$this->assertCount(1, $value);
$this->assertContains('|bar|baz', $value);
}
/**
* Test validate()
*
* @TODO Instead of having a lengthy list of assert calls, this could be
* implemented with data providers for each attribute type
*
* @return void
*/
public function testValidate()
{
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string);
$this->assertTrue($attrdef->validate('')); // even an empty string is valid
$this->assertTrue($attrdef->validate('foo')); // there is no invalid string
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '', '/[0-9]*S/');
$this->assertFalse($attrdef->validate('foo')); // doesn't match the regex
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_regex, $attrdef->getValidationError());
$this->assertTrue($attrdef->validate('S')); // no leading numbers needed
$this->assertTrue($attrdef->validate('8980S')); // leading numbers are ok
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, false, 0, 0, '|foo|bar|baz', '');
$this->assertTrue($attrdef->validate('foo')); // is part of value map
$this->assertFalse($attrdef->validate('foz')); // is not part of value map
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_valueset, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, true, 0, 0, '|foo|bar|baz', '');
$this->assertTrue($attrdef->validate('foo')); // is part of value map
$this->assertFalse($attrdef->validate('')); // an empty value cannot be in the valueset
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_valueset, $attrdef->getValidationError());
$this->assertTrue($attrdef->validate('|foo|baz')); // both are part of value map
$this->assertFalse($attrdef->validate('|foz|baz')); // 'foz' is not part of value map
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_valueset, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_string, true, 1, 1, '|foo|bar|baz', '');
$this->assertTrue($attrdef->validate('foo')); // is part of value map
$this->assertFalse($attrdef->validate('')); // empty string is invalid because of min values = 1
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_min_values, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('|foo|baz')); // both are part of value map, but only value is allowed
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_max_values, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_boolean);
$this->assertTrue($attrdef->validate(0));
$this->assertTrue($attrdef->validate(1));
$this->assertFalse($attrdef->validate(2));
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_boolean, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_int);
$this->assertTrue($attrdef->validate(0));
$this->assertTrue($attrdef->validate('0'));
$this->assertFalse($attrdef->validate('a'));
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_int, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_date);
$this->assertTrue($attrdef->validate('2021-09-30'));
$this->assertTrue($attrdef->validate('1968-02-29')); // 1968 was a leap year
$this->assertTrue($attrdef->validate('2000-02-29')); // 2000 was a leap year
$this->assertFalse($attrdef->validate('1900-02-29')); // 1900 didn't was a leap year
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('1970-02-29')); // 1970 didn't was a leap year
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('2010/02/28')); // This has the wrong format
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('1970-00-29')); // 0 month is not allowed
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('1970-01-00')); // 0 day is not allowed
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_date, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_float);
$this->assertTrue($attrdef->validate('0.567'));
$this->assertTrue($attrdef->validate('1000'));
$this->assertTrue($attrdef->validate('1000e3'));
$this->assertTrue($attrdef->validate('1000e-3'));
$this->assertTrue($attrdef->validate('-1000'));
$this->assertTrue($attrdef->validate('+1000'));
$this->assertFalse($attrdef->validate('0,567')); // wrong decimal point
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_float, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('0.56.7')); // two decimal point
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_float, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_email);
$this->assertTrue($attrdef->validate('info@seeddms.org'));
$this->assertTrue($attrdef->validate('info@seeddms.verylongtopleveldomain'));
$this->assertFalse($attrdef->validate('@seeddms.org')); // no user
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('info@localhost')); // no tld
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('info@@seeddms.org')); // double @
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$this->assertTrue($attrdef->validate('info@subsubdomain.subdomain.seeddms.org')); // multiple subdomains are ok
$this->assertFalse($attrdef->validate('info@seeddms..org')); // double . is not allowed
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('info@s.org')); // 2nd level domain name is too short
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$this->assertFalse($attrdef->validate('info@seeddms.o')); // top level domain name is too short
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$this->assertTrue($attrdef->validate('info@0123456789-0123456789-0123456789-0123456789-0123456789-01234567.org')); // domain name is 63 chars long, which is the max length
$this->assertFalse($attrdef->validate('info@0123456789-0123456789-0123456789-0123456789-0123456789-012345678.org')); // domain name is 1 char longer than 63 chars
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_email, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_url);
$this->assertTrue($attrdef->validate('http://seeddms.org'));
$this->assertTrue($attrdef->validate('https://seeddms.org'));
$this->assertFalse($attrdef->validate('ftp://seeddms.org')); // ftp is not allowed
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_url, $attrdef->getValidationError());
$this->assertTrue($attrdef->validate('http://localhost')); // no tld is just fine
$this->assertFalse($attrdef->validate('http://localhost.o')); // tld is to short
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_url, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user);
$attrdef->setDMS(self::getDmsMock());
$this->assertTrue($attrdef->validate(1));
$this->assertFalse($attrdef->validate(3));
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_user, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_group);
$attrdef->setDMS(self::getDmsMock());
$this->assertTrue($attrdef->validate('1'));
$this->assertTrue($attrdef->validate('2'));
$this->assertFalse($attrdef->validate('3')); // there is no group with id=3
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_group, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_group, true);
$attrdef->setDMS(self::getDmsMock());
$this->assertTrue($attrdef->validate(',1,2'));
$this->assertFalse($attrdef->validate(',1,2,3')); // there is no group with id=3
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_group, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user);
$attrdef->setDMS(self::getDmsMock());
$this->assertTrue($attrdef->validate('1'));
$this->assertTrue($attrdef->validate('2'));
$this->assertFalse($attrdef->validate('3')); // there is no user with id=3
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_user, $attrdef->getValidationError());
$attrdef = self::getAttributeDefinition(\SeedDMS_Core_AttributeDefinition::type_user, true);
$attrdef->setDMS(self::getDmsMock());
$this->assertTrue($attrdef->validate(',1,2'));
$this->assertFalse($attrdef->validate(',1,2,3')); // there is no user with id=3
$this->assertEquals(\SeedDMS_Core_AttributeDefinition::val_error_user, $attrdef->getValidationError());
}
}