Corda enums serialization and PersistentState - corda

I use Corda 4.1 and kotlin. My goal is to store some data to Corda databse using Persistence API and then do some queries(I follow the doc https://docs.corda.net/api-persistence.html ). I have small problem with querying enumerated types.
This enum
#CordaSerializable
enum class MyEnum {
A,
B,
C
}
is stored in the database table as integer values
0
1
2
And it looks like A corresponds 0, B corresponds 1, and C correponds 2.
But I do not see any explicit mappings. What rules are used to serialize enum values? can they be changed with some annotations?
Is there any simple way of ensuring that A enum value will be always saved as 0 in the database? Is it possible to persist just "A", "B", "C" directly instead of numbers?
I could do this maually implenmenting this logic in generateMappedObject function, but I am curious what is the right way

See here in the Kotlin specification: https://kotlinlang.org/docs/reference/enum-classes.html#working-with-enum-constants
Ordinals are allocated by the order in which they are declared within the Enum, and you can access the ordinal programmatically by calling MyEnum.A.ordinal
It doesn't look like there is any easy way to explicitly allocate ordinals like in C# where you can say enum { A = 2, B = 1, C = 0 }
You can also tell Hibernate to persist the mapping as a string by defining your column in the mapped entity as:
#Entity
#Table(name = "table_containing_en_enum"
class MyClass {
#Column(name = "enum")
#Enumerated(EnumType.STRING)
val enum: MyEnum,
...
}

Related

Provide a Converter for data-binding by defining a pair of SerializableFunction objects

In Vaadin 8 Framework, and Vaadin 10 Flow, the data-binding capability lets us provide a Converter to mediate between the widget’s expected data type (such as String for a TextField) and the data type of the backing bean property (such as Integer number).
In this example, the built-in Converter implementation StringToIntegerConverter is used.
binder
.forField( this.phaseField )
.withConverter(
new StringToIntegerConverter( "Must enter an integer number" )
)
.bind( Panel::getPhase , Panel::setPhase ) ;
But what about defining a Converter for other types? How can I easily define a short-and-sweet Converter? For example, a String-to-UUID converter. I want to show the canonical 36-character hex string in a TextField, and going the other direction, parse that string back into a UUID.
// String to UUID
UUID uuid = UUID.fromString( myString ) ;
// UUID to String
String myString = uuid.toString() ;
I see that Binder.BindingBuilder offers the pair of methods withConverter that both take a pair of SerializableFunction objects.
Binder.BindingBuilder::withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation)
Binder.BindingBuilder::withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation, String errorMessage)
➥ So how do I define the pair of SerializableFunction objects/classes?
I noticed that this interface lists a known subinterface ValueProvider<SOURCE,TARGET>. That looks familiar, and I have a hunch it is the key to easily defining a short simple converter. But I do not quite comprehend the syntax with lambdas and all that is going on here.
I am not asking how to write a class implementing Converter. I am asking how to write the pair of SerializableFunction arguments to pass to the Binder.BindingBuilder::withConverter methods listed above as bullet items.
Quoting that JavaDoc:
Interface Binder.BindingBuilder<BEAN,TARGET>
…
withConverter
default <NEWTARGET> Binder.BindingBuilder<BEAN,NEWTARGET> withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation)
Maps the binding to another data type using the mapping functions and a possible exception as the error message.
The mapping functions are used to convert between a presentation type, which must match the current target data type of the binding, and a model type, which can be any data type and becomes the new target type of the binding. When invoking bind(ValueProvider, Setter), the target type of the binding must match the getter/setter types.
For instance, a TextField can be bound to an integer-typed property using appropriate functions such as: withConverter(Integer::valueOf, String::valueOf);
Type Parameters:
NEWTARGET - the type to convert to
Parameters:
toModel - the function which can convert from the old target type to the new target type
toPresentation - the function which can convert from the new target type to the old target type
Returns:
a new binding with the appropriate type
Throws:
IllegalStateException - if bind has already been called
You can do it by passing two lambda expressions to withConverter, so something like this:
binder.forField(textField)
.withConverter(text -> UUID.fromString(text), uuid -> uuid.toString())
.bind(/* ... */);
If you need a more complicated conversion, then the right-hand side of the lambda can be surrounded with brackets, e.g.
binder.forField(textField).withConverter( text -> {
if ( text == null ) {
return something;
} else {
return somethingElse;
}
}, uuid -> { return uuid.toString(); } )
.bind(/* ... */);
If you need your converter multiple times, I recommend creating a separate class implementing interface com.vaadin.data.Converter. However, using lambdas is possible, too, as you already know (see answer of #ollitietavainen). But this is not Vaadin specific, it's a Java 8+ feature you can read about e.g. here. Basically, you can use lambdas whereever an object implementing an interface with only one method is required.

Qore: how to convert a hash to object

How can I convert a hash to and object? Suppose I have the following definition:
class A {
int i;
string s;
}
class B {
int bi;
A a;
}
hash h = (
"bi" : 100,
"A" : ("i" : 10, "s" : "str"));
is there any way how I could convert h to an object of class B?
Is this to be generic? If so, then you'd need a bit more verbose structure. Such that would make it clear that 'A' is to be an object, 'i' is to be an int, etc.
Anyway, there's a built-in function create_object that can be used to create an object as long as the object does not need constructor arguments or you know what they should be. Then you would set all members and that means they need to be public. You could also iterate object's public members and thus check if your hash provides all info.
I'm not aware of a way how to learn more about an object, such as member types, method signatures, etc. Still, you either know the object (so you can provide args to constructor or call a method after creation etc) or it has to be a simple object with no constructor args and public members (as private members cannot be set directly).

Entity Framework sort by Enum value alphabetically

I have an entity called Comment, which has an enum property of type CommentType:
public class Comment
{
public virtual Guid Id { get; private set; }
public virtual CommentType CommentType { get; set; }
// other prop removed for simplicity
}
public enum CommentType
{
Comment,
Correction,
Improvement,
BugFix,
NewFeauture,
Other
}
I need to select the comments from database by the alphabetically value of the CommentType enum, something like
_db.Comments.OrderBy(p => p.CommentType)
However, the Enum values are treated as integers, and the sort will not work alphabetically correctly.
Is there any way to add some attributes / metadata to the Enum values to make them sort correctly alphabetically?
One solution will be to assign the integer value to enum values, but i already have many database records that will need to be updated. And this solution is not good for new added enum values.
public enum CommentType
{
Comment = 2,
Correction = 3,
Improvement = 4,
BugFix = 1,
NewFeauture = 5,
Other = 6
}
Currently your enum name is not known at database level so in my opinion you have two options.
Use value on server side:
_db.Comments.ToList().OrderBy(p => p.CommentType.ToString())
Add value on database side: You should create table that will contain comment type names. And then you can create foreign key between comments and commentTypeNames and use simple select:
_db.Comments.OrderBy(c => c.CommentTypeNames.Name)
or just make join:
_db.Comments
.Join(
_db.CommentTypeNames,
c => c.CommentType,
ctn => ctn.CommentType,
(c, ctn) => new { Comment = c, CommentName = ctn })
.OrderBy(g => g.CommentName.Name)
.Select(g => g.Comment);
There are also computed columns. I never used those though so I dont have experience. Maybe you could add column that will be resolved to string by CASE statements on database. However I am not sure how will this affect performance/maintainability. For more info you could check http://geekswithblogs.net/DavidPaquette/archive/2012/09/23/calculated-columns-in-entity-framework-code-first-migrations.aspx
For performance reasons I would advise to take option 2, it's better to do such things in database.
I assume that you are using code first so maybe this post will be helpful for you: EF5 Code First Enums and Lookup Tables
This idea of a table is nice of course, especially when the enum has many values and is likely to get new ones. However, when enum values are added both the code and the database need to be maintained.
In general when the enum is volatile I would not use an enum but only the table.
But when it is not likely to change much, you could also consider to stick with the enum simply write out the order instruction:
_db.Comments.OrderBy(p =>
p.CommentType == CommentType.Comment ? "Comment" :
p.CommentType == CommentType.Correction ? "Correction" :
p.CommentType == CommentType.Improvement? "Improvement" :
.... :
"ZZZ")
As an alternative you may convert CommentType property in your Comment class into foreign key 'CommentTypeId' pointing at CommentType(Id, Name) table, that has your Id values and corresponding text Name.
This will let you order by text easily.

Why must JSR303 custom annotation's constrain group default to empty array?

I'm writing a custom validator for a specific constrain group (not Default), but the runtime gives me the below error.
I'm just curious why they need the default values to be empty. Appreciate if you can share your opinion. Thanks :)
xxx.model.validation.CustomValidation contains Constraint annotation, but the groups parameter default value is not the empty array.
StackTrace: org.hibernate.validator.metadata.ConstraintHelper.assertGroupsParameterExists(ConstraintHelper.java:335)
org.hibernate.validator.metadata.ConstraintHelper.isConstraintAnnotation(ConstraintHelper.java:282)
I can't figure out in which scenario it can be useful to bind a constraint to a specific group.
A group is used for partial validation (and sequence validation). If you have 10 fields in a class you can mark 8 of them with A and 2 with B. Then you can decide to validate only the fields in the A group or in the B group. Conversely you want that #MyConstraint belongs to a specific group named C. It makes no sense. A group is more or less a name used to distinguish some fields from others in the same class. It has no absolute meaning. Groups are useful in validation not in constraint definition, they are related to fields not to constraints.
Furthermore if you hide the group name in the constraint definition you may run into errors because you can think that the fields are validated all togheter.
#Email
private String mail;
#Password
private String pass;
#VAT
private String vatCode;
Are you able to see if there is a partial validation?
EDIT
In relation to the second comment:
Suppose you have a class with 5 fields with no constraint at all. Three of them are integers. If you want to validate the sum of these three fields you have to create a class-level constraint as you suggest. In this way your custom annotation is applied to the class not to fields so, how can you define groups on fields?
Instead, you may use something like this:
#Sum(min = 250, fields = {"length", "width", "height"})
public class MyClass {
private String type;
private String code;
private int length;
private int width;
private int height;
...
}

ASP.Net Entity Framework Repository & Linq

My scenario:
This is an ASP.NET 4.0 web app programmed via C#
I implement a repository pattern. My repositorys all share the same ObjectContext, which is stored in httpContext.Items. Each repository creates a new ObjectSet of type E. Heres some code from my repository:
public class Repository<E> : IRepository<E>, IDisposable
where E : class
{
private DataModelContainer _context = ContextHelper<DataModelContainer>.GetCurrentContext();
private IObjectSet<E> _objectSet;
private IObjectSet<E> objectSet
{
get
{
if (_objectSet == null)
{
_objectSet = this._context.CreateObjectSet<E>();
}
return _objectSet;
}
}
public IQueryable<E> GetQuery()
{
return objectSet;
}
Lets say I have 2 repositorys, 1 for states and 1 for countrys and want to create a linq query against both. Note that I use POCO classes with the entity framework. State and Country are 2 of these POCO classes.
Repository stateRepo = new Repository<State>();
Repository countryRepo = new Repository<Country>();
IEnumerable<State> states = (from s in _stateRepo.GetQuery()
join c in _countryRepo.GetQuery() on s.countryID equals c.countryID
select s).ToList();
Debug.WriteLine(states.First().Country.country)
essentially, I want to retrieve the state and the related country entity. The query only returns the state data... and I get a null argument exception on the Debug.WriteLine
LazyLoading is disabled in my .edmx... thats the way I want it.
You're doing a join without retrieving anything from it. There are multiple solutions to your problem:
Use Include to load the dependent entities: from s in ((ObjectSet<State>) _stateRepo.GetQuery).Include("Country"). The problem with this approach is that you should expose the ObjectSet directly rather than as a IQueryable if you want to avoid casting.
Use context.LoadProperty(states.First(), s => s.Country) to explicitly load the Country from the database for a given state.
Select both entities in the query: from s in ... join c ... select new { s, c }. You won't be able to access directly the state's Country property but you have it in the anonymous type.
Enable lazy loading.
Your repository implementation is very similar to mine, especially the way you are storing the ObjectContext. It works fine for me, so I don't think it's a conceptual problem.
Try using a static objectcontext (no wrapper) just to see if that fixes the problem. Perhaps there is a bug in your ContextHelper which causes your context to get disposed and recreated.

Resources