Grails: specify number of digits for integer in domain class - validation

Is there some better way than validators to enforce an integer be exactly, for example, 2 digits?
In my fantasy world I would do something like this:
class FantasyDomainClass{
Integer[2] twoDigitInteger //fantasy world knows I mean base 10
}
Maybe BigInteger?
Based on the answers posed, I am considering I may not want an integer as '01' is an acceptable value.

You can set a contraint on the field that it be between 10 and 99:
class FantasyDomainClass {
Integer twoDigitInteger
static constraints = {
twoDigitInteger min:10, max:99
}
}

I would go with a custom validator and set it as
class FantasyDomainClass {
Integer twoDigitInteger
static constraints = {
twoDigitInteger validator: {
return (it.toString().size() <= 2)
}
}

Related

How are shared/placed the int of the ProtoMember/ProtoInclude in ProtoBuf?

I've several questions on how/where the ID of a [ProtoContract] should be declared.
Imagine the following code:
[ProtoContract]
[ProtoInclude(100, typeof(SomeClassA))]//1) CAN I USE 1 here?
public abstract class RootClass{
[ProtoMember(1)]
public int NodeId {get;set;}
}
[ProtoContract]
[ProtoInclude(200, typeof(SomeClassC)]//2) Should I declare this here or directly on the RootClass?
//3) Can I use the id 100 here?
//4) Can I use the id 1 here? or member + include share the id?
public class SomeClassA : RootClass{
[ProtoMember(1)]//5) CAN I USE 1 here? Since the parent already use it but it's a different class
public String Name{get;set;}
}
[ProtoContract]
public class SomeClassC : SomeClassA {
[ProtoMember(2)]
public int Count{get;set;}
}
[ProtoContract]
public class SomeClassD : SomeClassA {
[ProtoMember(2)] //6) Can I use 2 here? Since SomeClassC already use it and is a sibling?
public int Count{get;set;}
}
I've put several number with questions:
CAN I USE 1 here?
Should I declare this here or directly on the RootClass?
Can I use the id 100 here?
Can I use the id 1 here? or member + include share the id?
CAN I USE 1 here? Since the parent already use it but it's a different class
Can I use 2 here? Since SomeClassC already use it and is a sibling?
The thing is that we have a huge model with a lot of classes, which all herits from the same object, so I'm trying to figure out to which ID I should take care.
Short version:
the set of field numbers for a type is the union of the numbers defined against members (fields and properties), and the numbers defined for immediate subtypes (includes)
the set of field numbers must be unique within that single type - it is not required to consider base types or derived types
Longer version:
The reason for this is that subtypes are essentially mapped as optional fields:
[ProtoContract]
[ProtoInclude(100, typeof(SomeClassA))]
public abstract class RootClass{
[ProtoMember(1)]
public int NodeId {get;set;}
}
[ProtoContract]
[ProtoInclude(200, typeof(SomeClassC)]
public class SomeClassA : RootClass{
[ProtoMember(1)]
public String Name{get;set;}
}
[ProtoContract]
public class SomeClassC : SomeClassA {
[ProtoMember(2)]
public int Count{get;set;}
}
is, in terms of proto2 syntax:
message RootClass {
optional int32 NodeId = 1;
optional SomeClassA _notNamed = 100;
}
message SomeClassA {
optional string Name = 1;
optional SomeClassC _notNamed = 200;
}
message SomeClassC {
optional int32 Count = 2;
}
Note that at most 1 sub-type field will be used, so it can be considered oneof for the purposes of .proto. Any fields relating to the sub-type will be included in message SomeClassA, so there is no conflict with RootClass and they do not need to be unique. The numbers only need to be unique per message in the .proto sense.
To take the specific questions, then:
no, because that would conflict with NodeId
it should be declared on SomeClassA; protobuf-net is only expecting immediate descendants, and it keeps the numbering consistent and conveniently readable, since the field number is only required to not conflict with the members of SomeClassA
yes you can; there is no conflict
no, because that would conflict with Name
yes you can; there is no conflict
yes you can; there is no conflict - although actually protobuf-net won't even think of SomeClassD as a sibling anyway (it isn't advertised anywhere as an include) - but if there was a [ProtoInclude(201, typeof(SomeClassD))] on SomeClassA, then it would be fine. This would change our .proto to add:
optional SomeClassD _alsoNotNamed = 201;
to message SomeClassA, and add:
message SomeClassD {
optional int32 Count = 2;
}
Note that protobuf-net doesn't actually generate the .proto syntax unless you explicitly ask for it (via GetSchema<T> etc) - I'm including it purely for illustrative purposes in terms of the underlying protobuf concepts.

Does Dart support enumerations?

Does Dart support enumerations? For instance:
enum myFruitEnum { Apple, Banana }
A cursory search of the docs suggests no.
Beginning 1.8, you can use enums like this:
enum Fruit {
apple, banana
}
main() {
var a = Fruit.apple;
switch (a) {
case Fruit.apple:
print('it is an apple');
break;
}
// get all the values of the enums
for (List<Fruit> value in Fruit.values) {
print(value);
}
// get the second value
print(Fruit.values[1]);
}
The old approach before 1.8:
class Fruit {
static const APPLE = const Fruit._(0);
static const BANANA = const Fruit._(1);
static get values => [APPLE, BANANA];
final int value;
const Fruit._(this.value);
}
Those static constants within the class are compile time constants, and this class can now be used in, for example, switch statements:
var a = Fruit.APPLE;
switch (a) {
case Fruit.APPLE:
print('Yes!');
break;
}
With r41815 Dart got native Enum support see http://dartbug.com/21416 and can be used like
enum Status {
none,
running,
stopped,
paused
}
void main() {
print(Status.values);
Status.values.forEach((v) => print('value: $v, index: ${v.index}'));
print('running: ${Status.running}, ${Status.running.index}');
print('running index: ${Status.values[1]}');
}
[Status.none, Status.running, Status.stopped, Status.paused]
value: Status.none, index: 0
value: Status.running, index: 1
value: Status.stopped, index: 2
value: Status.paused, index: 3
running: Status.running, 1
running index: Status.running
A limitation is that it is not possibly to set custom values for an enum item, they are automatically numbered.
More details at in this draft https://www.dartlang.org/docs/spec/EnumsTC52draft.pdf
Enumeration should be available in the future. But until Enum has landed you can do something like :
class Fruit {
static final APPLE = new Fruit._();
static final BANANA = new Fruit._();
static get values => [APPLE, BANANA];
Fruit._();
}
This and this may be the answers on your question:
... for the technology preview it was decided to leave it out and just
use static final fields for now. It may be added later.
You can still do something like this:
interface ConnectionState { }
class Connected implements ConnectionState { }
class Connecting implements ConnectionState { }
class Disconnected implements ConnectionState { }
//later
ConnectionState connectionState;
if (connectionState is Connecting) { ... }
wich is in my opinion more clear for use. It's a bit more difficult for programming the application structure, but in some cases, it's better and clear.
how about this approach:
class FruitEnums {
static const String Apple = "Apple";
static const String Banana = "Banana";
}
class EnumUsageExample {
void DoSomething(){
var fruit = FruitEnums.Apple;
String message;
switch(fruit){
case(FruitEnums.Apple):
message = "Now slicing $fruit.";
break;
default:
message = "Now slicing $fruit via default case.";
break;
}
}
}
Yes! Its actually very useful to do Enums in Dart:
enum fruits{
BANANA, APPLE, ORANGE
}
Just use Types Class File.
Dart-Types
easy, fast, more powerful and more helpful.
little problem, it is this class limited to five Different Choice and plus one for acts as null.
In case of anybody still searching for a quick solution for this.
We sometimes need integer value for an enum , sometimes string value. So we implement a quick package for this.
Enum Value Generator and an extension to easly generate necessary codes but this is not mandatory.vscode extension.
It is also capable of use with jsonAnnotation too.
import 'package:mobkit_generator/annotations.dart';
part 'example.g.dart'
#EnumSerializable(String)
enum PersonStr {
#EnumValue('John')
name,
#EnumValue('66')
number,
}
#EnumSerializable(int)
enum PersonInt {
#EnumValue(1)
name,
#EnumValue('66')
number,
}

In a Grails domain object, is it possible to validate a field based on another field?

I have a Grails domain object that looks like this:
class Product {
Boolean isDiscounted = false
Integer discountPercent = 0
static constraints = {
isDiscounted(nullable: false)
discountPercent(range:0..99)
}
I'd like to add a validator to discountPercent that will only validate if isDiscounted is true, something like this:
validator: { val, thisProduct ->
if (thisProduct.isDiscounted) {
// need to run the default validator here
thisProduct.discountPercent.validate() // not actual working code
} else {
thisProduct.discountPercent = null // reset discount percent
}
Does anyone know how I can do this?
This is more or less what you need (on the discountPercent field):
validator: { val, thisProduct ->
if (thisProduct.isDiscounted)
if (val < 0) {
return 'range.toosmall' //default code for this range constraint error
}
if (99 < val) {
return 'range.toobig' //default code for this range constraint error
} else {
return 'invalid.dependency'
}
You can't both have a special validator that relies on something else and have a special validator, as you can't run a single validator on a field (that I know of), only on single properties. But if you run a validation on this property, you'll depend on yourself and go into endless recursion. Therefore I added the range check manually. In your i18n files you can set up something like full.packet.path.FullClassName.invalid.dependency=Product not discounted.
Good luck!

How can i place validations for fields in groovy for specific format

I have Domain class and in that for a particular field of type String, it accepts alphanumeric values,i need a validation in the format it should accept only AB12-QW-1 (or) XY-12 values. how can i validate the field.
Please suggest the solution.
Thanks.
Assume your domain class looks like this
class Foo {
String bar
}
If you can define a regex that matches only the legal values, you can apply the constraint using:
class Foo {
String bar
constraints = {
bar(matches:"PUT-YOUR-REGEX-HERE")
}
}
Alternatively, if you can easily list all the legal values, you can use:
class Foo {
String bar
constraints = {
bar(inList:['AB12-QW-1', 'XY-12'])
}
}
If neither of these solutions will work, then you'll likely need to write a custom validator method
You could use a custom validator:
class YourDomain {
String code
static constraints = {
code( validator: {
if( !( it in [ 'AB12-QW-1', 'XY-12' ] ) ) return ['invalid.code']
})
}
}
However, your explanation of what codes are valid is a bit vague, so you probably want something else in place of the in call
[edit]
Assuming your two strings just showed placeholders for letters or numbers, the following regexp validator should work:
constraints = {
code( matches:'[A-Z]{2}[0-9]{2}-[A-Z]{2}-[0-9]|[A-Z]{2}-[0-9]{2}' )
}
And that will return the error yourDomain.code.matches.invalid if it fails

Custom Grails validation

I would like to check to make sure two fields are not equal and one is greater then the other. Say yearBorn and yearMarried. They cannot be equal and yearMarried must be greater then yearBorn.
You can use a 2-parameter custom validator that has access to both the value being validated and the entire instance:
static constraints = {
yearMarried validator: { year, instance ->
if (year == instance.yearBorn) {
return 'i18n.code.for.equal.value'
}
if (year <= instance.yearBorn) {
return 'i18n.code.for.born.after.married'
}
}
}

Resources