I am having a list of string as follows.
List l = ["1","2","3"]
And I have a class like as follows.
class person {
String name
}
I want to create a list of person object from List l.
I have tried using groovy list collect but I am not able to do so.
Here is my code.
class testJsonSlurper {
static void main(String[] args) {
List l = ["1","2","3"]
def l2 = l.collect { new person(it) }
println(l2)
}
}
But I getting following error.
Exception in thread "main" groovy.lang.GroovyRuntimeException: Could not find matching constructor for: testJsonSlurper$person(java.lang.String)
In your class testJsonSlurper, you have to change this line
def l2 = l.collect { new person(it) }
into
def l2 = l.collect { new person(name:it) }
This is what we call Named argument constructor. You can find more about Named argument constructor here.
If you do not want to make this change, then you need to add constructor in class person yourself.
The class person should look like this after adding constructor.
​class person {
String name
person(name){
this.name = name
}
}
First of all: I'm not an expert in protobuf.
Suppose I have such message structure:
package msg_RepAndOpt;
message RepAndOpt
{
repeated string name = 1;
optional string surname = 2;
...
// there are lots of others.
}
And I have two components that have copies of this message:
// component1:
RepAndOpt A;
A.add_name("Name");
A.set_surname("Surname");
// component2:
RepAndOpt B;
In my case components modify those messages via transaction mechanism. It means that if one component changes some field it also sends it to another component to propagate those changes. Component-receiver is doing merge:
// Component2 modifies B and sends it to component1.
// Component1 perfoms merge:
A.MergeFrom(B);
Now, say, component2 wants to erase field "name".
If it will send clear B message (default construction) than:
MergeFrom() will not modify A;
CopyFrom() will erase also other fields.
Another way will be to fill B with the contents of A, clear name field and component1 will use CopyFrom().
But this is not acceptable because system is really high-loaded and there could be lots of other fields.
So, desired solution to clean name field is:
Component2 create B message.
Explicitly stores information that it want to erase only name field.
Component1 perform A.MergeFrom(B).
Result: A::name is cleared but other fields are left untouched.
As far as I tested this applies to repeated and optional fields.
Is there any ready-to-use solution or I should modify protobuf implementation?
There is no builtin protobuf solution for your case. The obvious solution would be to iterate over all the fields in message A and check if that field is present in message B, if not you could clear it.
You can't solve this with basic MergeFrom(), but you may want to check out these from the protobuf library:
https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
https://github.com/google/protobuf/blob/master/src/google/protobuf/util/field_mask_util.h
In particular FieldMaskUtil::MergeMessageTo() seems to do what you want. You'll need to construct a FieldMask specifying exactly which fields you're interested in, so that other fields are left untouched.
UPD: updated after comments from Kenton Varda (see below).
Expanding one of the previous answers:
There is a way to solve it by adding new field in message definition (this works for proto v2):
repeated int32 fields_to_copy = 15;
This field will be filled by ID's of fields that would be copied (not merged) on the reciever side.
I also implemented this helper function:
// CopiableProtoMsg.hpp
#pragma once
#include <google/protobuf/message.h>
template <typename T>
void CopyMessageFields(const T& from, T& to)
{
const ::google::protobuf::Descriptor *desc = T::descriptor();
const ::google::protobuf::Reflection *thisRefl = from.GetReflection();
std::vector<const ::google::protobuf::FieldDescriptor*> fields;
int size = from.fields_to_copy_size();
for (int i = 0; i < size; ++i)
{
const ::google::protobuf::FieldDescriptor *field = desc->FindFieldByNumber(from.fields_to_copy(i));
fields.push_back(field);
}
T msgCopy(from);
thisRefl->SwapFields(&to, &msgCopy, fields);
to.clear_fields_to_copy();
}
This function checks fields_to_copy field and perform copying (via SwapFields()).
Here is the simple test:
RepAndOpt emulateSerialization(const RepAndOpt& B)
{
RepAndOpt BB;
std::string data;
B.SerializeToString(&data);
BB.ParseFromString(data);
return BB;
}
TEST(RepAndOptTest, additional_field_do_the_job_with_serialization)
{
RepAndOpt A;
RepAndOpt B;
A.add_name("1");
A.add_name("2");
A.add_name("3");
A.set_surname("A");
B.add_name("1");
B.add_name("3");
B.add_fields_to_copy(RepAndOpt::kNameFieldNumber);
RepAndOpt recvB = emulateSerialization(B);
A.MergeFrom(recvB);
CopyMessageFields(recvB, A);
EXPECT_EQ(2, A.name_size());
EXPECT_STREQ("1", A.name(0).c_str());
EXPECT_STREQ("3", A.name(1).c_str());
EXPECT_TRUE(A.has_surname());
EXPECT_EQ(0, A.fields_to_copy_size());
}
Expanding approach with field masks (that was proposed by Kenton Varda):
Note: This solution requires proto3, however the original message can be declared with proto2 syntax. (link to proof)
We can define a field mask field:
import "google/protobuf/field_mask.proto";
message RepAndOpt
{
repeated string name = 1;
optional string surname = 2;
optional google.protobuf.FieldMask field_mask = 3;
}
And here is the test usage:
RepAndOpt emulateSerialization(const RepAndOpt& B)
{
RepAndOpt BB;
std::string data;
B.SerializeToString(&data);
BB.ParseFromString(data);
return BB;
}
void mergeMessageTo(const RepAndOpt& src, RepAndOpt& dst)
{
dst.MergeFrom(src);
if (src.has_field_mask())
{
FieldMaskUtil::MergeOptions megreOpt;
megreOpt.set_replace_message_fields(true);
megreOpt.set_replace_repeated_fields(true);
FieldMaskUtil::MergeMessageTo(src, src.field_mask(), megreOpt, &dst);
}
}
TEST(RepAndOptTest, fix_merge_do_the_job_with_serialization_multiple_values)
{
RepAndOpt A;
A.add_name("A");
A.add_name("B");
A.add_name("C");
A.set_surname("surname");
RepAndOpt B;
B.add_name("A");
B.add_name("C");
B.mutable_field_mask()->add_paths("name");
mergeMessageTo(emulateSerialization(B), A);
EXPECT_EQ(2, A.name_size());
EXPECT_STREQ("A", A.name(0).c_str());
EXPECT_STREQ("C", A.name(1).c_str());
EXPECT_STREQ("surname", A.surname().c_str());
}
I had similar use case and ended up implement my own mixture based on that #Denis' answer.
Although the language was Golang, which doesn't have FieldMaskUtil with MergeOptions.
RepAndOpt.A.name RepAndOpt.B.name
remove ["A", "B", "C"] ["A"] => remove: A, keep: B, C
add ["A", "B", "C"] ["D"] => add: D, keep: A, B, C
add/remove ["A", "B", "C"] ["A", "D"] => remove: A, add: D, keep: B
In my project, I have some functions like that:
func 1 (with 2 class: class1 and classs1_1):
List<class1> GetData1(class1_1 cls)
{
List<class1> list = new List<class1>();
cls = new cls();
//do something for cls, like cls.GetSpecialCase();
//fill data from cls to list, as using foreach to fill data to list
return list;
}
func 2 (with 2 class: class2 and classs2_2):
List<class2> GetData2(class2_2 cls)
{
List<class2> list = new List<class2>();
cls = new cls();
//do something for cls, like cls.GetSpecialCase();
//fill data from cls to list, as using foreach to fill data to list
return list;
}
How could I write a function like that (because I don't want to use a lot of functions as above):
common func (with T is class1, object cls is class1_1):
List<T> GetData(object cls)
{
List<T> list = new List<T>();
//how to recognize which class of cls
if(cls == class1_1) class1_1 other_cls = cls as class1_1;
if(cls == class2_2) class2_2 other_cls = cls as class2_2;
//do something for other_cls
//fill data from other_cls to list
return list;
}
I just want to pass parameter as object, and in the common function, I want to know which class I'm passing to so that I can treat to right class, and call right function.
Anyone helps me to solve this problem.
Thank you very much.
It sounds like you need:
An interface or abstract base class with the GetSpecialCase method
A generic method (with type parameters for both input and output) of
List<TResult> GetData<T, TResult>(T item) where T : ISpecialCase<TResult>
{
List<TResult> list = new List<TResult>();
var other = item.GetSpecialCase();
// Fill list via other
return list;
}
If you can't introduce an interface or base class, you could use dynamic typing, but I'd strongly recommend that you use polymorphism to express what the different classes have in common (GetSpecialCase here) if you possibly can.
you can use generics also for the input type.
your code could be something like:
List<T> GetData<T>(T cls)
{
List<T> list = new List<T>();
//no need to recognize which class of cls
//do something for other_cls
//fill data from other_cls to list
return list;
}
and both classes needs to implement the same interface so you wouldn't need to know which type it is...
I'm sure there is a way to do this, but I'm really stuck on this one.
I have a domain model that connects to entities Foo and Bar in a many-to-many-relationship. Now when I want to list all Foos to a certain Bar, I do the query and get a lot of FooBar objects. I iterate through these objects and add all Foos to a list.
Like so:
def fooBarRelations = FooBar.findAllByBar bar
def fooList = []
fooBarRelations.each { fooList.add it.foo }
How can I sort the fooList based upon the parameters a g:sortableColumn adds to the url namely sort (the field to sort) and order.
I know you can pass the parameters to the query directly but I think this is not possible in my case?
So how can I either
Make one query without list iterating so I can pass in the sorting parameters OR
Sort my custom list based upon the sorting parameters?
Addition 1 (03/25/2012)
If I could to this ...
def fooBarRelations = FooBar.findAllByBar bar, [sort: 'foo.' + params.sort, order: params.order]
... the problem would be solved. But passing this to the query does not have any effect on the output. Is there any way I can sort a query by a sub-property?
If you really can't sort within the query itself. Then you need a list of lists.
List<List<Fields>> mylist;// where List<Fields> is a lists of the fields.
Then use a Comparator to sort your List> by the desired filed. Say your desired field is at index 3:
new Compare(List<Fields> L1, List<Fields> L2){
if(L1.get(3)>L2.get(3))
return -1;//etc.
UPATE BASED ON COMMENT:
say your entity is as follows
public class Entity{
String name, address, school;
Integer bankaccount;
//etc...
}
Then
public class WhereISort{
List<Entity> myList;
String mysorter;//mysorter can be declared here as static final
public WhereISort(){//maybe pass list in here or whatever
}
public Response myWebService(params..., String sorter){
mysorter=sorter;//mysorter can be declared here as static final
Collections.sort(myList, new Comparator() {
public int compare(Entity e1, Entity e2) {
if(mysorter.equalsIgnoreCase("name")){
return e1.getName().compareToIgnoreCase(e1.getName());
}else if(mysorter.equalsIgnoreCase("bankaccount")){
//your code here, etc.
}
}
});
}
}
Of course, the main point is using "mysorter" and the inner class "Comparator" to sort
I have a LINQ dbml class that I am wrapping in a POCO. I have built overloaded constructors that take the DBML class and init. the wrapper objects properties based on the dbml object passed in.
For example
public class MyPerson{
public MyPerson(DBMLPerson p)
{
this.ID = p.ID;
this.Name = p.Name;
}
}
if I then do something like this where I return an IQueryable
{
return from p in datacontext.DBMLPerson
select new MyPerson(p){};
}
When I try to do further queries on that Iquearble I get "System.NotSupportedException: The member 'MyPerson.ID' has no supported translation to SQL.."
However if I do this
{
return from p in datacontext.DBMLPerson
select new MyPerson(){
ID = p.ID;
Name = p.Name;
};
}
I don't get an error at all and everything works perfect. Basically I want to have my class handle the conversion from LINQ object to POCO itself.
Basically I have to use the Object Initializer or I am unable to match on that field.
Ok not sure this will actually help anyone but but myself but my whole problem is the I shouldn't be using IQuerable after a certain point(outside of my repository)
iqueryable-can-kill-your-dog-steal-your-wife-kill-your-will-to-live-etc