How to set priority of custom Oval constraint - preconditions

I have a custom Annotation constraint , but I want it to be checked only if the other constraint is valid .For example:
#NotNull
private String propertyA;
#Digits
private String propertyB;
if propertyA is null , i don't want "#Digits"on propertyB to be checked.
How can i solve the problem? Thanks.

You can use the "when" attribute, e.g.
#NotNull
private String propertyA;
#Digits(when="groovy:_this.propertyA!=null")
private String propertyB;
This example requires the Groovy runtime to be in the classpath. You can also use another scripting language, see http://oval.sourceforge.net/userguide.html#declaring-conditional-constraints

Related

why the second short form constructor gives the error that name and age must be initialized but not the commented ctor?

I am beginner in dart language.
So i created this class ..
class X{
String name;
int age;
// X(this.name,this.age);
X(name,age);
}
In this code the short form ctor X(name,age) gives error that name and age must be initilized but the ctor X(this.name,this.age) doesnt give such error.
In ctor X(this.name,this.age) compiler know that name and age will surely be initilized..
but in ctor X(name,age) why compiler cannot do that....(isn't it obvious that name and this.name is same thing).
please elaborate....
In Dart, if you don't specify any type, the language will assume you mean dynamic in this case.
So what your code is actually doing is:
class X{
String name;
int age;
X(dynamic name, dynamic age);
}
The problem then becomes that we don't assign these parameters to anything in the class since the name in the constructor would be a different name than the name in the class definition.
The analyzer would therefore complain about name and age not being provided a value since both fields are defined with non-nullable types and can therefore not be null (which is the default value for any variable in Dart regardless of its type).
The this.name and this.age is a shortcut to the following code:
class X{
String name;
int age;
X(String name, int age) : name = name, age = age;
}
The name = name works because we are not allowed to set the parameter to some other value in the initializer part of the constructor. So Dart can assume that the first name must mean the class variable while the second name means the parameter, since the parameter is the one closest in scope.

Spring Data Neo4j neo4jTemplate.fetch() only returns one value

I'm converting a working system that uses #Fetch to a lazy load strategy. However, when I retrieve the object with a container, the container only has one entry and neo4jTemplate.fetch(obj.getContainer()) does not retrieve the other entries.
Here are the pertinent snippets
#NodeEntity
public class SourcePage {
#GraphId
private Long id;
#RelatedTo(type = "GROUP_MEMBER")
private Group group;
Group Class:
#NodeEntity
public class Group {
#GraphId
private Long id;
#RelatedTo(type = "GROUP_MEMBER", direction = Direction.INCOMING)
private Set<SourcePage> sourcePages = new HashSet<>();
Test Code:
Group group1 = groupRepository.findByName("Test Group");
neo4jTemplate.fetch(group1.getSourcePages());
assertThat(group1.getSourcePages().size(), is(254));
The Result:
java.lang.AssertionError:
Expected: is <254>
but: was <1>
If I do nothing but add #Fetch to private Group group, then it all works as expected.
Also, I looked at the database server with only this test example and ran this query:
MATCH (a)-[:`GROUP_MEMBER`]->(b) RETURN count(b)
It returned 254 as expected. I have also tried direction.BOTH on each side of the relationship - same results.
I found the problem. It's esoteric and plausible enough that it might help someone else seeing the same symptom.
First, I didn't show that I had my own hashCode() for SourcePage. It hashed a field defined as:
#NotEmpty
#Indexed
private String url;
Without #Fetch the 'url' is not retrieved automatically, so all the SourcePages in the container have the same hash code. This resulted in 100% collisions and only one entry added to the set.
If I removed the hashCode() then the default hash worked and all the objects were added to the set.
After several hours of debugging, I posted my question. Of course right after that I stumbled on the solution.
Moral of the story: don't provide a hash function on member data without the ID.

MVC DataAnnotation Accept No Spaces

I'm developing a Login View in MVC5.
I would like to set at the ViewModel level a DataAnnotation to state the the field does NOT accept empty spaces.
Is there a Data Annotation in MVC (something like [NoSpaces] that can be used to NOT allow a string field to contain "spaces" ?
How about this:
[RegularExpression(#"^\S*$", ErrorMessage = "No white space allowed")]
Well, the simplest but robust thing I can think of is to look at how existing code works, or how existing data annotation work.
For example, let's look at the System.ComponentModel.DataAnnotations.StringLengthAttribute class.
Here's the definition only (just to keep short):
namespace System.ComponentModel.DataAnnotations
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public class StringLengthAttribute : ValidationAttribute
{
public StringLengthAttribute(int maximumLength);
public int MinimumLength { get; set; }
public override string FormatErrorMessage(string name);
public override bool IsValid(object value);
}
}
So I would simply copy the original implementation source code from GitHub and customize it to my needs. For example, to obtain a signature like this (if I understood correctly and this is what you wanted):
public StringLengthAttribute(int maximumLength, int minLength = 0, allowEmptySpaces = true);
For more in-depth info, I would also read the Microsoft docs on the ValidationAttribute class, which is your base class for custom validation data annotations.
EDIT:
I would NOT rely on Regular Expressions to validate data in cases where I just need to exclude empty strings or strings containing only white space(s), because Regular Expressions are very expensive to process (and require a lot of memory allocation, because of an expression compiler, a state machine, etc.).
If this is convenient for anyone, I got pass this issue by doing this on the client:
//trim each form input
var $form = $("#myForm");
$form.find("input:text").each(function(){
var $self= $(this);
$self.va($self.val().trim());
});
//then validate before submit
if($form.valid()){ $form.submit(); }
// on the server ModelState.Isvalid does verify each item with [Required] and won't accept only white spaces from an input (but this means additional roundtrip to server and it's not always convenient)

How to get a node using index

I have an entity Place:
#NodeEntity
#TypeAlias(value="Place")
public class Place implements Serializable{
private static final long serialVersionUID = 1L;
#GraphId
private Long nodeId;
#JsonProperty("id")
#Indexed(unique=true)
private String id;
//...
}
And I try to get a node based on its id attribute this way:
String pfc = "1234";
(Node)template.getIndex(Place.class, "id").get("id", pfc).getSingle()
But I'm having this exception :
java.lang.IllegalStateException: Index name for class java.lang.String id rel: false idx: true must differ from the default name: Place
Must I necessairly add a name to the index?
If yes, how should I do for the existent data?
Which version are you using? In SDN 3.x for Neo4j 2.x the indexes and constraints are used automatically.
I would use a PlaceRepository with a findById() method.
Or in general cypher queries that access place like this:
MATCH (p:Place {id:{id}})-->(x)
RETURN x
You can access them manually with template.merge() or template.findByLabelAndProperty() which I would only recommend when you know what you're doing.

MVC - Change Compare attribute error message

In my MVC application I have the ability to get the error message from a text file instead of using the default error message. This works perfectly on the Required attribute (both Serverside and Clientside).
I now need to do the same with the Compare attribute, but I can't figure out how to override the Compare attribute.
For reference, this is how I am doing it with the Required attribute (I would like similar code to this to work with the Compare attribute)...
Public Class RequiredFieldAttribute
Inherits ValidationAttribute
Implements IClientValidatable
Private innerAttribute As New RequiredAttribute()
Private errormessagecontrolid As String
Public Sub New(ErrorMessageControlID As String)
Me.errormessagecontrolid = ErrorMessageControlID
End Sub
Protected Overrides Function IsValid(value As Object, validationContext As ValidationContext) As ValidationResult
If Not innerAttribute.IsValid(value) Then
Return New ValidationResult(ErrorMsgs.Text(Me.errormessagecontrolid))
End If
Return ValidationResult.Success
End Function
Public Function GetClientValidationRules(metadata As ModelMetadata, context As ControllerContext) As IEnumerable(Of ModelClientValidationRule) Implements IClientValidatable.GetClientValidationRules
Dim result = New List(Of ModelClientValidationRule)
Dim rule = New ModelClientValidationRule() With {.ErrorMessage = ErrorMsgs.Text(Me.errormessagecontrolid), .ValidationType = "required"}
result.Add(rule)
Return result
End Function
End Class
Above, ErrorMsgs.Text is the function that retieves the message from the text file. Against my model I then apply something like this...
<RequiredField("AccountDetailsPostcodeError")>
Public Property PostCode As String
The system then looks in the Text file for an entry called AccountDetailsPostcodeError.
How can I achieve the same with the Compare attribute. At the moment I have a hard coded error message like this...
<Compare("WebPassword", ErrorMessage:="The password and confirmation do not match.")>
Public Property ConfirmWebPassword As String
Edit: The suggested fix below may work in C#, but won't work in VB.NET, hence my more complex requirement to override the Compare attribute. I just don't know how to correctly override it.
Why use a text file for your translations and messages, .NET has build in options for translations. You can use resources. The advantage of using resources is that resources are type safe, they are checked as compile time. Where your textfile can become corrupt / missing.
The following guide helps you with setting up resources in a Mvc project:
Step one
Edit the default assembly language:
(C#) Properties > Assembly information > Neutral Language
(VB) My Project > Assembly information > Neutral Language
Set this language to your default language. (For this example I use English (United States))
Step two
Add a resource file to your project. Call this file Resource.resx. Open this file. Change the Access Modifier to Public and start adding resource strings. For example:
Step three
Add for each other language you want to support another resource file but name them Resource.LANGUAGE.resx where LANGUAGE is replaced by the other culture name. For culture names you can check this url: http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx
Then fill the new resource file with the localized strings. For example:
Step four
Then you can in your Models use the default localization support of the attributes:
For example:
VB:
Imports System.ComponentModel.DataAnnotations
Public Class UserModel
<Display(Name:="UserNameField", ResourceType:=GetType(My.Resources.Resource))>
<Required(AllowEmptyStrings:=False, ErrorMessageResourceName:="RequiredUsername", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
Public Property UserName As String
<Display(Name:="PasswordField", ResourceType:=GetType(My.Resources.Resource))>
<MinLength(6, ErrorMessageResourceName:="PasswordLengthError", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
<Compare("PasswordAgain", ErrorMessageResourceName:="CompareError", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
<Required(AllowEmptyStrings:=False, ErrorMessageResourceName:="RequiredPassword", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
Public Property Password As String
<Display(Name:="PasswordAgainField", ResourceType:=GetType(My.Resources.Resource))>
<Required(AllowEmptyStrings:=False, ErrorMessageResourceName:="RequiredPasswordAgain", ErrorMessageResourceType:=GetType(My.Resources.Resource))>
Public Property PasswordAgain As String
End Class
C#
using System.ComponentModel.DataAnnotations;
public class UserModel
{
[Display(Name = "UserNameField", ResourceType = typeof(My.Resources.Resource))]
[Required(AllowEmptyStrings = False, ErrorMessageResourceName = "RequiredUsername", ErrorMessageResourceType = typeof(My.Resources.Resource))]
public string UserName;
[Display(Name = "PasswordField", ResourceType = typeof(My.Resources.Resource))]
[MinLength(6, ErrorMessageResourceName = "PasswordLengthError", ErrorMessageResourceType = typeof(My.Resources.Resource))]
[Compare("PasswordAgain", ErrorMessageResourceName = "CompareError", ErrorMessageResourceType = typeof(My.Resources.Resource))]
[Required(AllowEmptyStrings = False, ErrorMessageResourceName = "RequiredPassword", ErrorMessageResourceType = typeof(My.Resources.Resource))]
public string Password;
[Display(Name = "PasswordAgainField", ResourceType = typeof(My.Resources.Resource))]
[Required(AllowEmptyStrings = False, ErrorMessageResourceName = "RequiredPasswordAgain", ErrorMessageResourceType = typeof(My.Resources.Resource))]
public string PasswordAgain;
}
For localization the attribute needs to know the name of the static property and the type of the static class where to get the property from (as seen above).
Step five
Then in your view use the #Html.ValidationSummary() to get all the error messages, or use
VB #Html.ValidationMessageFor(Function(model) model.Property)
C# #Html.ValidationMessageFor(m => m.Property)
to get specific error messages.
For the display attribute you can use:
VB #Html.DisplayNameFor(Function(model) model.Property)
C# #Html.DisplayNameFor(m => m.Property)
Changing the language
And last but not least you can change the language of your app instead of your neutral language defined in step one by editing the Web.config and changing the globalization tag like so:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<globalization uiCulture="nl" />
</system.web>
</configuration>
If you want to change the language from code you should edit System.Threading.Thread.CurrentThread.CurrentUICulture for information about this I suggest google or another SO question.
Example project
For this question I quickly made an example project to provide an accurate answer. Project can be found here:
MvcVBTest.V1.zip
UPDATE
If you don't want to use Resources but a single text file you can use the same concept the resource framework uses. You need a class that has static properties you can reference.
For this purpose I did the following things:
I created a class called Resources (Resources.vb).
In this class I added a sub class called Resource
In the static constructor of this class I open resource.xml which I have mapped to an array of Resource
This array is then converted to an Dictionary(Of String, String)
I created an static get property for every item in the xml. And returned the right item from the Dictionary
I changed the ResourceType parameter in the UserModel class
And of course a little clean up. The old resources can be deleted and the globalization tag can be removed from the web.config.
Now all the text can be found in resource.xml as key value pairs. To add another line, add it to the XML and create a property for it in the Resource class.
Example project
For this update I updated my example project:
MvcVBTest.V2.zip
Why not use something like this?
<RequiredField(ErrorMessage=GetErrorMessage())>
Just create a static function that gets the error message for you. You can even take a parameter for your GetErrorMessage function so you can determine which message you'll want to return.

Resources