[Bean Validation] @Pattern
by Emmanuel Bernard
I had a lot of demands for regexp support and since there is a need
for string matching in the built-in constraints...
http://opensource.atlassian.com/projects/hibernate/browse/HV-121
I replaced the bitwise guru flags approach with an enum
@Pattern( regexp = ".*", flags = { Pattern.Flag.CANON_EQ })
String name;
/**
* The annotated String must match the following regular expression.
* The regular expression follows the Java regular expression conventions
* see {@link java.util.regex.Pattern}.
*
* Accepts String.
*
* @author Emmanuel Bernard
*
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
public @interface Pattern {
/**
* regular expression to match
*/
String regexp();
/**
* Flags considered when resolving the regular expression
*/
Flag[] flags() default {};
/**
* error message template
*/
String message() default "{validator.past}";
/**
* groups the constraint belongs to
*/
Class<?>[] groups() default { };
/**
* Possible Regexp flags
*/
public static enum Flag {
/**
* Enables Unix lines mode
* @see java.util.regex.Pattern#UNIX_LINES
*/
UNIX_LINES,
/**
* Enables case-insensitive matching
* @see java.util.regex.Pattern#CASE_INSENSITIVE
*/
CASE_INSENSITIVE,
/**
* Permits whitespace and comments in pattern
* @see java.util.regex.Pattern#COMMENTS
*/
COMMENTS,
/**
* Enables multiline mode
* @see java.util.regex.Pattern#MULTILINE
*/
MULTILINE,
/**
* Enables dotall mode
* @see java.util.regex.Pattern#DOTALL
*/
DOTALL,
/**
* Enables Unicode-aware case folding
* @see java.util.regex.Pattern#UNICODE_CASE
*/
UNICODE_CASE,
/**
* Enables canonical equivalence
* @see java.util.regex.Pattern#CANON_EQ
*/
CANON_EQ,
}
}
16 years, 2 months
[Bean Validation] Groups and Group sequence
by Emmanuel Bernard
On Feb 6, 2009, at 02:37, Sebastian Thomschke wrote:
>> Also I could not find the answer in the spec for the following:
>>> @GroupSequence(sequence = {GroupA.class, GroupB.class}
>>> interface MyGroup extends GroupC, GroupD { }
>>>
>>> => my guess is, this is a group of GroupA,GroupB,GroupC,GroupD where
>>> GroupA and GroupB must be validated first.
>>>
>>> I wonder if it would make sence to change this to something like
>>> this:
>>>
>>> @Group(sequence = {GroupA.class, GroupB.class}
>>> interface MyGroup extends GroupA, GroupB, GroupC, GroupD { }
>>>
>>> In this case the aggregation of groups is always done via
>>> inheritance
>>> and only the ordering is done via an annotation. The constraint
>>> would be
>>> that the group must inherit directly or indirectly the classes
>>> listed in
>>> the sequence parameter.
>>>
>>> Any thoughts?
>> hum I will need to think harder about that one. not in the mood right
>> now. Give me time.
> I am eagerly waiting for your response :-)
So that's a complex topic :) And it unveiled some underdefined parts
in the spec.
It also raised more questions than answers. so anyway here we go.
Please comment on each case.
1. Can an annotation declaration use a group sequence name?
Initially I thought that a sequence was here for the sole purpose of:
- redefinining the Default group of a class
- a group defined and used at validation time ie
validator.validate(object, groupSequenceName)
Should we allow a GS to be used in a declaration
@GroupSequence(sequence=LightBillable.class, HeavyBillable.class)
interface Billable {}
@NotNull(groups=LightBillable.class)
CreditCard defaultCreditCard;
@NotNull(groups=Billable.class)
Address defaultBillingAddress;
And in this case, should the GS name group be validated in parallel to
the actual group sequence constraint.
While I don't think it's a great practice to use group sequence names
in a constraint declaration, I haven't found a compelling argument
against it.
WDYT?
Likewise
2. Should we allow superinterfaces on GroupSequence definitions?
same question, same arguments as 1.
3. When defining sequence between two groups, should their supergroups
be naturally ordered?
* I can find cases where "inherited" ordering make sense
interface LightBillable extends Default {}
interface HeavyBillable {}
@GroupSequence(sequence=LightBillable.class, HeavyBillable.class)
interface Billable {}
We want Default to be validated before HeavyBillable.
* I can find cases where "inherited" ordering is annoying
interface SafeUser {}
interface Billable extends Default, SafeUser {}
interface Shippable extends Default, SafeUser {}
@GroupSequence(Billable.class, Shippable.class)
interface CanOrder {}
Billable, SafeUser, Default must be before Shippable, SafeUser,
Default which is impossible ( SafeUser befire Default and Default
before SafeUser).
But realistically, such a constraint would better off be modeled as
interface SafeUser {}
interface Billable {}
interface Shippable {}
@GroupSequence(Billable.class, Shippable.class)
interface CanOrder extends Default, SafeUser {}
or
interface SafeUser {}
interface Billable {}
interface Shippable {}
interface ValidAndBillable extends Default, SafeUser {}
@GroupSequence(ValidAndBillable.class, Shippable.class)
interface CanOrder {}
4. Should we consider group sequence as orthogonal to inheritance as
described by Sebastian
interface SafeUser {}
interface Billable {}
interface Shippable {}
interface ValidAndBillable extends Default, SafeUser {}
@GroupSequence(ValidAndBillable.class, Shippable.class)
interface CanOrder extends ValidAndBillable, Shippable {}
Pro side:
Any circular dependency between group sequences / inheritance is
caught by the compiler (though, a sequence incompatibility is not).
Con side:
@GroupSequence used by classes to override the default sequence will
not follow this rule
@GroupSequence(Default.class, HeavyUserValidation.class)
class User { ... }
Comments welcome.
Once we answer the question, I will adjust the group formal definition
(should be easy) and clarify what group sequence means.
16 years, 2 months
Hibernate styled maven site
by Hardy Ferentschik
Hi,
Now that more and more projects switched to maven, are there any plans to
deploy the maven generated site as publicly
available documentation? And if so, has anyone worked on a Hibernate style
for such a site?
--Hardy
16 years, 2 months
Maven plugin
by Alaa Mohsen
Hello guys,
My IDE is whining about maven-jdocbook-plugin since the beginning of
the week now. I added the JBoss repository to my local POM file, but I
suggest that it should be added to the SVN. What do you think?
16 years, 2 months
[Bean Validation] Relax property names in ConstraintValidatorContext
by Emmanuel Bernard
Property names passed to
context.addError(message, "myProperty");
used to be limited to existing properties and could only be used if
the constraint declaration was on the class-level.
Otherwise, an exception was raised.
I relaxed this rule as some people came with use cases involving
validating property values by navigating properties hosted on the
property value.
@SafeZipCodeAndCity
public Address getAddress() { ... }
Here is the new wording
Example 2.13. ConstraintValidatorContext interface passed to
ConstraintValidator.isValid()
/**
* Provide contextual data and operation when applying a given
constraint validator implementation
*
* @author Emmanuel Bernard
*/
public interface ConstraintValidatorContext {
/**
* Disable default error message and default ConstraintViolation
object generation.
* Useful to set a different error message or generate an
ConstraintViolation based on
* a different property
*
* @see #addError(String)
* @see #addError(String, String)
*/
void disableDefaultError();
/**
* @return the current unexpanded default message
*/
String getDefaultErrorMessage();
/**
* Add a new error message. This error message will be interpolated.
* <p/>
* If isValid returns false, a ConstraintViolation object will be
built per error message
* including the default one unless #disableDefaultError() has been
called.
* <p/>
* Aside from the error message, ConstraintViolation objects
generated from such a call
* contains the same contextual information (root bean, path and so on)
* <p/>
* This method can be called multiple time. One ConstraintViolation
instance per
* call is created.
*
* @param message new unexpanded error message
*/
void addError(String message);
/**
* Add a new error message to a given sub property <code>property</
code>.
* This error message will be interpolated.
* <p/>
* If isValid returns false, a ConstraintViolation object will be built
* per error message including the default one unless
#disableDefaultError()
* has been called.
* <p/>
*
* @param message new unexpanded error message
* @param property property name the ConstraintViolation is targeting
*/
void addError(String message, String property);
}
The ConstraintValidatorContext interface allows to redefine the
default message error generated when a constraint is not valid. By
default, each invalid constraint leads to the generation of one error
object represented by a ConstraintViolation object. This object is
build from the default error message as defined by the constraint
declaration and the context in which the constraint declaration is
placed on (bean, property, attribute).
The ConstraintValidatorContext methods let the constraint
implementation disable the default error object generation and create
one or more custom ones. The unexpanded message passed as a parameter
is used to build the ConstraintViolation object (the message
interpolation operation is applied to it). The property on which the
error object is applied is defined as following:
if property is not overridden, the current context the constraint is
declared on is used (bean or property)
if the property is overridden, the current context the constraint is
declared on the property passed as a parameter relative to the
constraint declaration being evaluated
The property can be overridden by calling
ConstraintValidatorContext.addError(String, String).
16 years, 2 months
[BVAL-RI] Regarding BVAL-90
by Alaa Mohsen
Hello All,
What's the status of BVAL-90 (Stop using a properties file for built-in
constraints and move to a list in Java)? I'm thinking of implementing it
using a static map that's get filled on class loading. I wanted to have a
clean implementation using reflection, but can't find a clean solution to
get the classes within a package. I'm also thinking of using an enum instead
of a map. What do you think?
Regards,
Alaa Nassef
16 years, 3 months
[BVAL-RI] Renamed several constraints
by Alaa Mohsen
Hi all,
To follow the naming convention, I renamed the constraint validators for
Past, Null and NotNull. I created a JIRA issue for that BVAL-105, and
attached the patches
16 years, 3 months
[BVAL-RI] Implementing built in constraint validators
by Alaa Mohsen
Hello Guys,
I implemented most constraint validators yesterday and added a patch on
JIRA. There was a small bug in the AssertFalse validator, and I fixed it,
and added another patch to be used in place of the one attached yesterday.
Wasn't able to delete the old attachemnt, since I don't have this authority
on the JIRA
Regards
Alaa Nassef
16 years, 3 months