Grails data binding - data-binding

A Grails controller received is called with the following request parameters:
defaultPrice[0].amount 22
defaultPrice[0].currency 1
defaultPrice[0].id
defaultPrice[1].amount 33
defaultPrice[1].currency 3
defaultPrice[1].id
I've defined the following command class:
class PriceCommand {
BigDecimal amount
Integer currency
Integer id
}
I attempt to bind the request parameters to a `List' in the action
def save = {List<PriceCommand> defaultPrice ->
}
But within the action, defaultPrice is null.

It requires an command with existing list of data, with specified name, that will be filled with data from request.
Try
import org.apache.commons.collections.ListUtils
import org.apache.commons.collections.Factory
class PriceListCommand {
List<PriceCommand> defaultPrice = ListUtils.lazyList([], {new PriceCommand()} as Factory)
}
and use this command inside controller. It should works

I'm not sure if this is what your looking but it may help...
1.) I think indexed params only work if you have a parent-child or one-to-many relationship. For example you might need to introduce a PriceCommandParent which contains a list of PriceCommand. I may be wrong on this and I welcome any corrections.
2.) I've found that indexed params aren't as magically as some of the other areas of Grails/Groovy so sometimes i'd rather deal with the mapping myself. Below is how i've handled it in the past....
def things = []
params.each{name, value->
if (name.matches('^(thing\\[\\d+\\])$')){ //<-- look for 'thing[x]'
things.add(new Thing(params[name]);
}
}
Let me know if any of this is of help

Related

Dart - Casting List<SuperType> to List<SubType> using generics

I am new to Flutter and Dart, coming from native Android.
Android has a very nice database abstraction architecture called the Room Persistence Library. As far as I am aware, no such database abstraction architecture exists for Flutter using the MVVM / MVC design patterns.
My solution was to create a Dart version of it myself. I got it pretty much done after a few headaches, but I cannot seem to get LiveData to work properly using generics.
I set up my class like this:
class LiveData<T> {
...
}
Now when I want to return some data, it can either be an Object or List<Object>. I found a neat hack for differentiating the two from T:
...
// Parse response
// This checks if the type is an instance of a single entity or a list.
if (entity is T) {
cachedData = rawData.isEmpty ? null : entity.fromMap(rawData.first) as T;
} else {
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
}
...
The problem lies in the second block:
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
With the error:
- Unhandled Exception: type 'List<Entity>' is not a subtype of type 'List<Vehicle>' in type cast
The question then becomes: How can I cast Entity to Vehicle when I do not have access to the Vehicle class. Only an instance of it is assigned to an Entity entity variable.
Here's a snippet to demonstrate my access to Vehicle:
final Entity entity;
...assign Vehicle instance to entity...
print(entity is Vehicle) // True
I've tried using .runtimeType to no avail. I have also thought about splitting LiveData into two classes, the second one being LiveDataList. Although this seems to be the easiest solution to not bug the code- it would bug me (bad pun is intentional) and break the otherwise pretty direct port of Room.
As a temporary solution, I have abstracted out the build logic into a generic function to be passed to the LiveData in the constructor.
final T Function(List<Map<String, dynamic>> rawData) builder;
And now I call that instead of the previous code to build the cachedData.
// Parse response
cachedData = builder(rawData);
With the constructor for the LiveData<List<Vehicle>> called when accessing all vehicles in the Dao<Vehicle> being:
class VehicleDao implements Dao<Vehicle> {
...
static LiveData<List<Vehicle>> get() {
return LiveData<List<Vehicle>>(
...
(rawData) => rawData.map((e) => Vehicle.fromMap(e)).toList(),
...
);
}
}
In Dart (and indeed in many languages) generics screws with the concept of inheritance. You would think that if Bar inherits from Foo, that List<Bar> would also be castable to List<Foo>.
This is not actually going to be the case because of how generics work. When you have a generic class, every time you use that class with a different type, that type is treated as a completely separate class. This is because when the compiler compiles those types, class MyGenericType<Foo> extends BaseClass and class MyGenericType<Bar> extends BaseClass are basically converted to something like class MyGenericType_Foo extends BaseClass and class MyGenericType_Bar extends BaseClass.
Do you see the problem? MyGenericType_Foo and MyGenericType_Bar are not descendants of one another. They are siblings of each other, both extending from BaseClass. This is why when you try to convert a List<Entity> to List<Vehicle>, the cast doesn't work because they are sibling types, not a supertype and subtype.
With all this being said, while you cannot directly cast one generic type to another based on the relationship of the generic type parameter, in the case of List there is a way to convert one List type to another: the cast method.
List<Entity> entityList = <Entity>[...];
List<Vehicle> vehicleList = entityList.cast<Vehicle>(); // This cast will work
One thing to note though, if you are casting from a supertype generic to a sub-type generic and not all the elements of the list are that new type, this cast will throw an error.

WF4 Business Rules

I want to pass a object to workflow as input parameter, without creating instance of it, as this object is already filled up with lot of sub-objects, and I want to run lot of rules on that object. I want to use
WorkflowInvoker.Invoker(this); Is this possible in Windows Workflow Foundation 4.0, If so, what should I keep in InArguments as the type?
Thanks In Advance,
Thanks for your input....
Sorry, I think I haven't kept the question correctly, I had a business class used by bank customers, class is like this,
public partial class BankName.DTOS.clsCardDetails : BaseClass
{
public string _mBankStatusCode;
protected override string IsCreditCard(HttpContext ctx)
{
Status = ctx.Request.Form["Trans_Status"];
_mBankStatusCode = Status.ToString();
}
}
Now, I have to pass this class object to workflow foundation, I should not create new instance of this class in workflow again. Because in workflow, I want to get the status, so ideally what I thought of passing to workflow is object of "BankName.DTOS.clsCardDetails". That is my question.
InArguments<> to workflow is object of BankName.DTOS.clsCardDetails
Arguments passed into a workflow need to be put into a dictionary and the dictionary is passed into the workflow.
var dictionary = new Dictionary<string, object> { { "BankName", _bankNameObject } };
WorkflowInvoker.Invoke(this, dictionary);
The key must have the same name as your InArgument and your object must have the same type as your InArgument.
You can pass as many arguments as you like into the workflow via the dictionary.
See http://blogs.msdn.com/b/rjacobs/archive/2011/05/26/passing-arguments-to-workflow-activities-again.aspx

LINQ and web service cannot return anonymous types, and you cannot construct an object in a query?

Web services cannot return an anonymous type.
If you are building a LINQ query using classes through a datacontext... you cannot construct instances of those classes in a query.
Why would I want to do this? Say I want to join three "tables" or sets of objects. I have three items with a foreign key to each other. And say the lowest, most detailed of these was represented by a class that had fields from the other two to represent the data from those. In my LINQ query I would want to return a list of the lowest, most detailed class. This is one way I have decided to "join some tables together" and return data from each of them via LINQ to SQL via a WebService. This may be bad practice. I certainly do not like adding the additional properties to the lowest level class.
Consider something like this... (please ignore the naming conventions, they are driven by internal consideration) also for some reason I need to instantiate an anonymous type for the join... I don't know why that is... if I do not do it this way I get an error...
from su in _dataContext.GetTable<StateUpdate>()
join sfs in _dataContext.GetTable<SystemFacetState>()
on new { su.lngSystemFacetState } equals new { lngSystemFacetState = sfs.lngSystemFacetState }
join sf in _dataContext.GetTable<SystemFacet>()
on new { sfs.lngSystemFacet } equals new { lngSystemFacet = sf.lngSystemFacet }
join s in _dataContext.GetTable<System>()
on new { sf.lngSystem } equals new {lngSystem = s.lngSystem}
select new
{
lngStateUpdate = su.lngStateUpdate,
strSystemFacet = sf.strSystemFacet,
strSystemFacetState = sfs.strSystemFacetState,
dtmStateUpdate = su.dtmStateUpdate,
dtmEndTime = su.dtmEndTime,
lngDuration = su.lngDuration,
strSystem = s.strSystem
}
).ToList();
Notice I have to build the anonymous type which is composed of pieces of each type. Then I have to do something like this... (convert it to a known type for transport via the web service)
result = new List<StateUpdate>(from a in qr select(new StateUpdate
{
lngStateUpdate = a.lngStateUpdate,
strSystemFacet = a.strSystemFacet,
strSystemFacetState = a.strSystemFacetState,
dtmStateUpdate = a.dtmStateUpdate,
dtmEndTime = a.dtmEndTime,
lngDuration = a.lngDuration,
strSystem = a.strSystem
}));
It is just awful. And perhaps I have created an awful mess. If I am way way off track here please guide me to the light. I feel I am missing something fundamental here when I am adding all these "unmapped" properties to the StateUpdate class.
I hope someone can see what I am doing here so I can get a better way to do it.
You can create a 'dto' class which just contains the properties you need to return and populate it instead of the anonymous object:
public class Result
{
public string lngStateUpdate
{
get;
set;
}
... // other properties
}
then use it like this:
from su in _dataContext.GetTable<StateUpdate>()
...
select new Result
{
lngStateUpdate = su.lngStateUpdate,
... // other properties
}
Nitpick note - please ditch the Hungarian notation and camel casing for properties :)
I think the answer is to create another object to serve as a DTO. This object would not be mapped to the data context and can contain fields that cross the mapped objects. This solves the problems of repetitive properties in the mapped objects, and allows for instantiation of the DTO class in the query as it is not mapped.
FYI: with respect to the problem with the join- I revisited that and I think I may have had the inner and outer components of the join switched around before.

Breeze: How can I create a GUID key for new entities on the client?

Using Breeze, what is the simplest way to populate a GUID key when an entity is created?
I'll assume that your entity is configured such that the client is responsible for setting the Guid key for new entities. That's the default for the Guid key of an Entity Framework Code First entity; it is as if the key property were adorned with [DatabaseGenerated(DatabaseGeneratedOption.None)]
The obvious approach is to set the key after creating the entity and before adding it to the manager, e.g.:
function createFoo() {
var foo = fooType.createEntity();
foo.id(breeze.core.getUuid()); // Knockout implementation
manager.addEntity(foo);
}
This may be all you ever need.
On the other hand, you may find that you're creating new Foos in many places and for some strange reason you can't use the createFoo function. You certainly don't want to repeat that code.
You can extend the Foo entity type with id-setting behavior after which you'd be able to write:
function createFoo() {
var foo = fooType.createEntity(); // foo.id is set for you
manager.addEntity(foo);
}
There are two approaches to consider - custom constructor and type initializer; both are described in "Extending Entities"
Constructor
You can initialize the key inside a custom constructor. Breeze calls the constructor both when you create the entity and when it materializes a queried entity. Breeze will replace the initial key value when materializing.
Here's an example that assumes the Knockout model library.
function Foo() {
foo.id(breeze.core.getUuid()); // using KO
}
// one way to get the MetadataStore
var store = manager.metadataStore;
// register the ctor with the Foo type
store.registerEntityTypeCtor("Foo", Foo);
Pretty simple. The only downside is that Breeze will generate a Guid every time it makes an entity, whether creating a new one or materializing one from a query. It's wasted effort during materialization but so what? Well, I suppose that might become a performance issue although I wouldn't assume so until I had measured it.
Initializer
Suppose you measured and the repeated Guid generation is a serious problem (really?). You could set the key in a type initializer instead and only call the Guid generator when creating a new entity.
Breeze calls a type initializer after the entity has been created or materialized from query just before returning that entity to the application. Clearly you don't want to overwrite a materialized key from the database so you'll test the key value to make sure it's not real (i.e. to make sure you're fixing a created entity) before assigning it. Here's an example.
function fooInitializer(foo) {
var emptyGuid = "00000000-0000-0000-0000-000000000000";
if (foo.id() !=== emptyGuid) {
foo.id(breeze.core.getUuid());
}
}
var store = manager.metadataStore;
// register the initializer; no ctor in this example
store.registerEntityTypeCtor("Foo", function(){}, fooInitializer);
Assuming you have a Guid surrogate Key on all your entities like we have in our case, you could code a createInstance factory that does the following in a very generic approach:
function createInstance(breezeEntityManager, typeName) {
var keyProperty = breezeEntityManager.metadataStore.getEntityType(typeName, false).dataProperties.filter(function (p) {
return p.isPartOfKey;
})[0];
var config = {};
config[keyProperty.name] = breeze.core.getUuid();
return breezeEntityManager.createEntity(typeName, config);
}
This way, you won't have to create an initializer for all your entities.

copy a Collection element by value in C#

In the code below, a reference type is being added. How can i do this value type?
imgList.Items.Add(imgList.Items[0]);
imgList.Items[imgIndex].Data = input; <== **This updates the 0th and the newly added element which is the issues**
Please advise
In order to avoid this issue, you need to clone imgList.Items[0] before adding it to imgList.Items. This basically involves creating a new object of the same type and populating it with data from the original.
The complexity of doing so depends on what the object is, but look at the answers to this question for some tips on cloning objects.
Edit: I forgot that .MemberwiseClone was protected.
You don't say in your code what the type of object is that you're adding to the list. If it's a class of yours, you can add a method to return a copy:
public MyType ShallowCopy()
{
return (MyType)this.MemberwiseClone();
}
and use
imgList.Items.Add(imgList.Items[0].ShallowCopy());
Or you can add a copy constructor:
public MyType(MyType original)
{
// Copy each of the properties from original
this.Data = original.Data;
}
and use
imgList.Items.Add(new MyType(imgList.Items[0]));

Resources