JSR-303 doesn't support such a scenario? - bean-validation

I try to validate beans by Hibernate Validator. It should be programable and based on a JSON config file.
data models:
class A {
field,
other fields
}
class B {
class A a,
other fields
}
class C {
class A a,
other fields
}
class D {
class B b,
class C c,
other fields
}
Validate D based on a JSON config file.
The config file wants to validate the following:
D.b.a.field should not be null.
D.c.a.field is nullable.
Using program way, I set the validation like this:
constraintMapping
.type( D.class )
.property( "b", FIELD )
.constraint( new NotNullDef() )
.valid()
.type( B.class )
.property( "a", FIELD )
.constraint( new NotNullDef() )
.valid()
.type ( A.class )
.property( "field", FIELD )
.constraint( new NotNullDef() );
Now, the A.field has been set to not null validator, but the problem is, now the D.c.a.filed also cannot be null.
This is just an example, I absolutely don't want to change the data models.

Using groups at constraint level might help you solve your problem. To add a group to constraint you just need to call group method and pass a list of groups in which the constraint should be included:
constraintMapping
.type( D.class )
.property( "b", FIELD )
.constraint( new NotNullDef().groups( SomeGroup.class )
.valid()
And then you could create different groups for different "validation paths" and use them when validating an object. Thant might not work great though if your validation configs are fully dynamic.Also see the doc for more info on groups.

#mark-o, I tested the following solution, but I failed.
It validates field1 and field2 for both GroupB and GroupC,
but my expectation is validating field1 only for GroupB but not for GroupC,
and validate field2 only for GroupC but not for GroupB.
A little change for Class A (has field1 and field2), and add a wrapper for class A which is used by both class B and class C.
constraintMapping
.type( D.class )
.property( "b", FIELD )
.constraint( new NotNullDef().groups(GroupB.class) )
.valid()
.property( "c", FIELD )
.constraint( new NotNullDef().groups(GroupC.class) )
.valid()
.type( B.class )
.property( "aWrapper", FIELD )
.constraint( new NotNullDef().groups(GroupB.class) )
.valid()
.type( C.class )
.property( "aWrapper", FIELD )
.constraint( new NotNullDef().groups(GroupC.class) )
.valid()
.type ( AWrapper.class )
.property( "a", FIELD )
.constraint( new NotNullDef().groups(GroupB.class, GroupC.class) )
.valid()
.type ( A.class )
.property( "field1", FIELD )
.constraint( new NotNullDef().groups(GroupB.class) )
.property( "field2", FIELD )
.constraint( new NotNullDef().groups(GroupC.class) );

Related

Faunadb conditional statement can't run false condition expression

I tried to build fulltext search API using nextjs and faunadb.
I referenced the article "How to Get a Full-Text Search with FaunaDB"
My index setting is as below.
This API will receive two values artist and term(short for search term)
If there is two, it will combined by and statement.
Or it will run there own statement or each value.
Implemented code is as below.
const queryCase = req.body.artist && req.body.term ? 1 : req.body.term != undefined ? 2 : 3
const tokens = await serverClient.query(
Filter(
Paginate(Match(Index("all_token_by_artist_and_description"), true)),
Lambda(
[
"artist",
"description",
"image",
"seller",
"creator",
"category",
"refId"
],
If(
Equals(queryCase, 1),
And(
Or(
ContainsStr(
LowerCase(Var("artist")),
req.body.term
),
ContainsStr(
LowerCase(Var("description")),
req.body.term
)
),
Equals(
LowerCase(Var('artist')),
LowerCase(req.body.artist)
)
),
If(
Equals(queryCase, 2),
Or(
ContainsStr(
LowerCase(Var("artist")),
req.body.term
),
ContainsStr(
LowerCase(Var("description")),
req.body.term
)
),
Equals(
LowerCase(Var('artist')),
LowerCase(req.body.artist)
)
)
)
)
)
)
res.status(200).json(tokens.data)
It couldn't run false condition expression. The false expression works fine
when I switched truth expression and false expression.
I get it fixed by make 3 separate query.
if(queryCase == 1){
tokens = await serverClient.query(
.....
)
}else if(queryCase == 2){
tokens = await serverClient.query(
.....
)
}else{
tokens = await serverClient.query(
.....
)
}
But I really have no idea what's wrong with the original query.
Can anyone tell me the problem with the query?
It caused by missing value. So I assigned random string to the missing value after the case is determined.
eg) If I only get "artist" value from request, assign random string to the "term".

Modify cell in a R DT::datatable based on previous row

I have a shiny app where I would like to modify the data displayed and/or the attributes of a cell based on the value of the same cell in the previous row.
In my code I have formatted whole rows based on the value of data[0] in rowCallback.
output$result <- DT::renderDataTable(tabledata(),
class = c('compact'),
rownames = FALSE,
server = FALSE,
escape = TRUE,
extensions = options = list(
rowCallback=JS("
function (row, data, index) {
var string=data[1], substring = 'sub total';
if (data[0]=='Grand Total') {
$(row).css('background-color', '#DEDEDE'), $(row).css('font-weight', 'bold') ;
}
else if (data[0].includes('sub total')) {
$(row).css('font-weight', 'bold');
}
}"
)
)
)
Can I achieve a modification of the data[0] cell based on the value of the same cell in the previous row using one of the callback functions?
So I changed tack and used the following drawCallback call
drawCallback=JS(" function ( settings ) {
var api = this.api();
var mydata = api.rows( {page:'current'} ).data();
var last=null;
api.column(0,{page:'current'}).data().each( function ( value, index ) {
if ( value == last) {
mydata[index][0] = ''
api.rows({ page: 'current' }).invalidate();
}
last=value;
});
}"
)

ZF2 Doctrine with Symfony < OR null query

How do I write this "WHERE" condition in a way which is compatible with Doctrine?
( ( `translations_es_google`.`translation_date` < `translations_masters`.`translation_date` ) OR ( `translations_es_google`.`translation_date` is null ) )
What I have tried (unsuccessfully) are:
$query1
->andWhere('((t.translationDate < m.translationDate) OR (t.translationDate is NULL))');
$query1
->andWhere('(t.translationDate < m.translationDate) OR (t.translationDate is NULL)');
Table alias for the Doctrine query are
t represents the table translations_es_google
m represents the table translations_masters
When I remove this "andWhere" condition the rest of the QueryBuilder query executes as expected.
The query I am trying to execute is
SELECT
`translations_masters`.`translation_key` , `translations_masters`.`text_domain` , `translations_masters`.`translation_date`
FROM
`translations_masters`
LEFT JOIN
`translations_es_google` ON ( ( `translations_masters`.`text_domain` = `translations_es_google`.`text_domain` ) AND ( `translations_masters`.`translation_key` =`translations_es_google`.`translation_key` ) )
WHERE
`translations_masters`.`language_iso` NOT LIKE 'es-Google' AND ( ( `translations_es_google`.`translation_date` < `translations_masters`.`translation_date` ) OR ( `translations_es_google`.`translation_date` is null ) )
GROUP BY
`translations_masters`.`translation_key` , `translations_masters`.`text_domain`
ORDER BY
`translations_masters`.`translation_date` ASC
As requested the QueryBuilder version of this query is:
$query1 = $this->entityManager
->createQueryBuilder()
->select('m.textDomain , m.translationKey , m.translationDate , m.translationDate AS translationMasterDate , t.translationDate')
->from(
'AMDatabase\Entity\TheVerse\Translations' . $explode1 . $explode2,
't'
)
->leftJoin(
'AMDatabase\Entity\TheVerse\TranslationsMasters',
'm',
Join::WITH,
'(m.textDomain = t.textDomain) AND (m.translationKey = t.translationKey)'
)
->groupBy('m.textDomain , m.translationKey')
->orderBy(
'm.translationDate',
'ASC'
)
->setMaxResults('1');
$query1
->andWhere(
$query1->expr()
->notLike(
'm.languageIso',
':languageIso'
)
)
->setParameter(
'languageIso',
$value
);
$query1->andWhere(
$query1->expr()->orX(
't.translationDate < m.translationDate',
't.translationDate IS NULL'
)
);
$result1 = $query1->getQuery()
->getArrayResult();
The output of $query1->getQuery()->getSQL() is
SELECT
t0_.text_domain AS text_domain_0, t0_.translation_key AS translation_key_1, t0_.translation_date AS translation_date_2, t0_.translation_date AS translation_date_3, t1_.translation_date AS translation_date_4
FROM
thev1010_theverseoftheday.translations_es_google t1_
LEFT JOIN
thev1010_theverseoftheday.translations_masters t0_ ON ((t0_.text_domain = t1_.text_domain) AND (t0_.translation_key = t1_.translation_key))
WHERE
t0_.language_iso NOT LIKE ? AND (t1_.translation_date < t0_.translation_date OR t1_.translation_date IS NULL)
GROUP BY
t0_.text_domain, t0_.translation_key
ORDER BY
t0_.translation_date ASC
LIMIT 1
The ? value is 'es-Google'
The output of $query1->getQuery()->getDQL(); is
SELECT
m.textDomain , m.translationKey , m.translationDate , m.translationDate AS translationMasterDate , t.translationDate
FROM
AMDatabase\Entity\TheVerse\TranslationsEsGoogle t
LEFT JOIN
AMDatabase\Entity\TheVerse\TranslationsMasters m WITH (m.textDomain = t.textDomain) AND (m.translationKey = t.translationKey)
WHERE
m.languageIso NOT LIKE :languageIso AND (t.translationDate < m.translationDate OR t.translationDate IS NULL)
GROUP BY
m.textDomain , m.translationKey
ORDER BY
m.translationDate ASC
The ? value is 'es-Google'
How about orX expression?
You can try it this way:
$query1->andWhere(
$query1->expr()->orxX(
't.translationDate < m.translationDate',
't.translationDate IS NULL'
)
);
orX gives you the ability to add multiple conditions, separated by comma.
You can also separate your orX condition to its own variable and pass everything added to it to andWhere condition.

search with Doctrine if blank field

i have written a DQL query for my multiple search,working fine if i specify the all fields but if i keep one of the field blank it won't show me the result
$query = $em->createQuery
('SELECT d FROM EntityBundle:Doctor d WHERE d.name =:name AND d.degree =:degree AND d.area = :area_id AND d.sex = :sex AND
(
( YEAR(d.dob) BETWEEN :d2 AND :d1 ) OR
( YEAR(d.dob) BETWEEN :e2 AND :e1 ) OR
( YEAR(d.dob) BETWEEN :f2 AND :f1 )
)' )
->setParameter('name', $name)
->setParameter('degree', $degree)
->setParameter('area_id', $area)
->setParameter('sex', $sex)
->setParameter('d1', $this->p1)
->setParameter('d2', $this->p2)
->setParameter('e1', $this->q1)
->setParameter('e2', $this->q2)
->setParameter('f1', $this->r1)
->setParameter('f2', $this->r2)
->getResult();
i have tried setParameter('name', (is_null($name)? "IS NULL" : $name)) also but still there is no luck..
You can use QueryBuilder instead of DQL
$qb = $qb->select('d');
if($name !== null) {
$qb = $qb->where('d.name = :name')->setParameter(...);
}
...
$qb->getQuery()->getResult();

form.SchemaEditForm with ignoreContext

everybody
I'm trying to make an edit form for an object other than the context. It's a dictionary stored in the session. I'm following Martin Aspeli Schema Drive Forms. It should be easy, but for some reason, the edit form doesn't load any data. Maybe I'm losing some simple detail, but I can't find it. I made ignoreContext=True and tried returning a dictionary and after that an instance that implements the schema, but it didn't work.
from plone.directives import form, dexterity
from zope.interface import invariant, Invalid, implements
class IUser(form.Schema):
'''Represents an user'''
uid = schema.TextLine(
title = _(u'Login'),
)
gn = schema.TextLine(
title = _(u'Name'),
)
sn = schema.TextLine(
title = _(u'Surname'),
)
uniqueIdentifier = schema.TextLine(
title = _(u'Identifier'),
description = _(u'Ej. V11222333'),
)
accClass = schema.TextLine(
title = _(u'User class'),
)
dateExpiration = schema.TextLine(
title = _(u'Date of expiration'),
)
class User:
implements(IUser)
def __init__(self, **kargs):
self.uid = kargs['uid']
self.gn = kargs['givenName']
self.sn = kargs['sn']
self.uniqueIdentifier = kargs['uniqueIdentifier']
self.accClass = kargs['accClass']
self.dateExpiration = kargs.get('dateExpiration', '2015/06')
class Edit(form.SchemaEditForm):
'''Modify User'''
grok.context(IUserManager) # It's ok. This is a view of an IUserManager object
grok.require('zope2.View') # <- just for testing
grok.name('modify')
schema = IUser
ignoreContext = True
label = 'Modify an User'
def getContent(self):
# I've tried returning a dictionary too, but it's useless
user = User(**SessionUsers(self.context).current())
return user

Resources