Populate properties of an object from array of String - arrays

If we have an object in groovy, for example Customer[name, email, phone] and a String in the form
String infoLine = "Stanislav,stanislav#stackoverflow.com,004612345678"
What is the easiest way to parse that string and populate the fields of that object?
(The example string we can split, that is why the question is from array of String)

Assuming you have a constructor
Customer(String name, String email, String phone)
You can do:
new Customer(*infoLine.split(','))
If you don't want to write a constructor, you can get Groovy to create one for you:
import groovy.transform.*
#TupleConstructor
class Customer {
String name
String email
String phone
}
String infoLine = "Stanislav,stanislav#stackoverflow.com,004612345678"
new Customer(*infoLine.split(','))
Or even better, #Immutable as this makes the properties final
#Immutable
class Customer {
String name
String email
String phone
}
Another option (assuming your fields are defined in the order they appear in the string, and there are no other fields), would be to generate a map of [name: 'aaa', emai... etc, and tell groovy to convert the map to a Customer like:
class Customer {
String name
String email
String phone
}
String infoLine = "Stanislav,stanislav#stackoverflow.com,004612345678"
def customer = [
Customer.declaredFields.findAll { !it.synthetic }*.name,
infoLine.split(',')
].transpose().collectEntries() as Customer
But this feels kinda brittle, and it's probably quicker to add the annotation or constructor.

Related

How to build a list of dynamic strings in Flutter?

I'm coding an app/game where user inputs his own rules on textfields stored in a SQFLite database.
Rules are related to a friend, so it's in a class Friend, with an id, name, rule0, rule1, rule2...rule9. Which is REALLY annoying for a lot of reasons, but I think I need it to be in Friend class so it get stored with the right friend.id.
I got the obvious error 'only static members can be accessed on initializers' when i try
List<Strings> rules = [rule0, rule1];
or
List<dynamic> rules = [...];
Does anyone knows how I could fix this ?
Create a new class Rules and each rule has ID related to the right friend ?
Or if I can just create a dynamic list whithin Friend ?
Really lost on this. Any help is welcome.
class Friend {
int id;
String name;
String pic;
bool play;
String rule0;
String rule1;
String rule2;
String rule3;
String rule4;
String rule5;
String rule6;
String rule7;
String rule8;
String rule9;
Friend();
// i have then a fromMap() and a toMap() for the database
}
I'm not completely sure, but it seems like you're having trouble with both the SQL aspect as well as the class representation of your data.
If you know for sure there will only be a set number of rules, you could approach it in the way you currently have. The addition I'd do is to make a 'getter' function for the list of rules i.e.
List<String> get rules => [rule1, rule2, rule2, ...].where((item) => item != null).toList()
Note that if you were using a constructor, you could instead build the list in the constructor as follows:
class Friend {
int id;
String name;
String pic;
bool play;
String rule0;
String rule1;
String rule2;
String rule3;
String rule4;
String rule5;
String rule6;
String rule7;
String rule8;
String rule9;
List<String> rules;
Friend(
{this.id,
this.name,
this.pic,
this.play,
this.rule0,
this.rule1,
this.rule2,
this.rule3,
this.rule4,
this.rule5,
this.rule6,
this.rule7,
this.rule8,
this.rule9})
: rules = [
rule0,
rule1,
rule2,
rule3,
rule4,
rule5,
rule6,
rule7,
rule8,
rule9,
].where((item) => item != null).toList(growable: false);
}
I wouldn't recommend that though (or if you do, you should probably be making either rule* or rules private or maintaining state somehow). The list of strings doesn't store references to the rule0, rule1, ... strings but rather stores the strings themselves. You could get around this by making a Rule class and making rule0-9 final, but that's getting a bit complicated.
It most likely makes more sense for this to be a dynamic list of items. SQL doesn't handle that, so you're going to have to make a separate table for rules.
You'll have two tables something like this, where id are both PRIMARY KEYs and friendId is a FOREIGN KEY:
Friend(id, name, pic, play) and Rule(id, friendId, text)
Saving and updating will become more complicated now. You'll have to be more careful about maintaining the list of rules in the database, but it isn't all that difficult. If you know that you'll only be writing to the list from one location (i.e. one class), you could keep the difference between what the class's current state and the initial state were, but realistically unless you're dealing with 10's of thousands of rules, it probably won't matter appreciably.

Using only one dataprovider , how to pass data to many test methods

Im using DataProvider in TestNG for my Selenium Scripts . My requirement is to just use a single DataProvider and pass the data to many test methods .
For example : Say i have 10 test methods , So i need to create a Single DataProvider , so that it can pass data to all those 10 Test methods.
Is it possible to do it ? If yes , how to implement it .
Or is there any alternative for this ??
Pl Help !!!
If each of your test method has #Test annotation, then you can simply add parameter to this as -
#Test(dataProvider="Name of your DataProvider")
You can do this with all of the 10 test methods & this will make them get data from your single DataProvider.
I hope it helps. . .cheers!!
Yes it is possible.
So your data provider needs to know for which method or class it is providing the data. I made the following implementation. So you can get the context of the calling method in a data provider and you can ask it what is the parent class name for which the data has to be provided, and then depending on that you can have multiple files which you can read and supply the data or have different rows in the same csv differentiated by class name from where you can read the required row
#DataProvider(name="getDataFromFile")
public static Iterator<Object[]> getDataFromFile(Method testMethod) throws Exception
{
String expected=null;
String className=testMethod.getDeclaringClass().getSimpleName();
Reporter.log("Providing data for class " + className,true);
List<Map<String, String>> setupData = getTestDataFromCsv(classname);
//provide data here
}
Update on this:
I was looking for a solution for the same. But it is not possible to split the data provider. But no harm in reusing the data provider for all methods, the disadvantage is each method must use the complete list of arguments. All other options are more complex to implement and maintain. For my scenario, it is better than creating and maintaining separate data providers for each test methods.
#BeforeMethod
public void setUp() {
init();
login= new LoginPage(myD);
clientsearch = new ClientSearchPage(myD);
toppanel= new TopPanelPage(myD);
}
#Test(dataProvider="search_data")
public void verifySearchByClientNumber(String clientnumber, String policynumber, String policynumberClient, String webreference,
String webreferenceClient, String surname, String surnameClient, String forename, String forenameClient, String dob, String dobClient){
login.Login();
log.info("Logged in successfully, now in ClientSearch Page..");
log.info("Entering client number.." );
clientsearch.enterClientNumber(clientnumber);
log.info("Clicking on the Search button ..." );
clientsearch.clickSearchButton();
log.info("Verifying Client present in results.." );
boolean res=clientsearch.isClientPresent(clientnumber);
Assert.assertEquals(res, true,"Assertion failed !!");
toppanel.clickLogoutButton();
}
#Test(dataProvider="search_data")
public void verifySearchByPolicyNumber(String clientnumber, String policynumber, String policynumberClient, String webreference,
String webreferenceClient, String surname, String surnameClient, String forename, String forenameClient, String dob, String dobClient){
login.Login();
log.info("Logged in successfully, now in ClientSearch Page..");
log.info("Entering Policy number.." );
clientsearch.enterPolicyNumber(policynumber);
log.info("Clicking on the Search button ..." );
clientsearch.clickSearchButton();
log.info("Verifying Client present in results.." );
boolean res=clientsearch.isClientPresent(policynumberClient);
Assert.assertEquals(res, true,"Assertion failed !!");
toppanel.clickLogoutButton();
}
//More methods here with same data provider....
#AfterMethod
public void endTest() {
myD.quit();
}

Getting Dapper to return an empty string instead of a null string

I know it's kind of the wrong thing to do, but I'm dealing with a legacy codebase that has NULLS when it means empty strings and vice versa.
I can't immediately see how it is possible, but is it possible to get (or modifiy dapper so it will) return an empty string instead of a null string when mapping back from the database.
Dapper doesn't call any setter when it sees a null, so options might include:
set the default value to "" in the constructor
check for null in the accessor
So:
public class SomeDto
{
public SomeDto()
{
Name = "";
}
public string Name {get;set;}
}
or:
public class SomeDto
{
private string name;
public string Name { get {return name ?? "";} set {name = value;} }
}
However, this only applies to reading values; I can't think of a nice way to get dapper to turn "" into null when passing the dto in as the parameter object; options include:
creating an anon-type, substituting "" to null (perhaps write a string NullIfBlank(this string s) extension method)
having a shim property on the type that returns null in place of "", and have your database query bind to #NameOrNull rather than #Name
You can control this with your queries, for example:
public class Data
{
public string Foo { get; set; }
}
var result = conn.Query<Data>("select Foo = coalesce(Foo, '') from MyTable");
So in the above example, coalesce will return an empty string when Foo is null.
In short: depending how you load the data to the dapper you may get two different scenarios.
First: Turn up your data provider layer, for example like in this post - How to return null from a Dapper query rather than default(T)?.
Second way to try: you may modify your GetTypeDeserializer like in the following post - Change Dapper so that it maps a database null value to double.NaN
Third and the last: it is my friendly advice to work on your previous questions acceptance rate. In this way you may increase chances of replies for your questions.
Hope all this will help.
I tend to use a global extension method on string called ConvertNull() which converts any null values to an empty string. You can then call this anywhere without your code looking cluttered. If you're using this directly on an aspx page, just make sure you've imported the namespace of the extension methods and then the method will be available to you:
namespace ExtensionMethods
{
using System;
public static class StringExtensionsClass
{
/// <summary>Converts null strings to empty strings</summary>
/// <param name="s">Input string</param>
/// <returns>Original string, or empty string if original string was null</returns>
public static string ConvertNull(this string s)
{
return s ?? "";
}
}
}
Then call this on an instance of a string.
Usage:
myStringInstance.ConvertNull().Replace("\r\n", "<br />");

Camel, Bindy and composed fields

I'm trying to unmarshal a csv that have composed fields. For instance, in the following example
"order1","foo#email.com","(test1;45),(test2;89)"
The third attribute would represent a list of two items (but the size of the list is variablet), each item having a name and a price. The #Link annotation only works in one-to-one annotation, so it is not an option. The #OneToMany annotation in csv only works for writting so is neither an option.
The csv is written by non technical stuff, so a complex format is not an option either.
Is it possible to manage this requirement?
The java class to instantiate would be, in this case, something like this:
public class Order {
private String name;
private String email;
private List<Item> items;
}
public class Item {
private String name;
private int price;
}
Many thanks in advance

User Image/Profile fields - Database normalization - Social Networking - Grails

Should I normalize the users profile_image_url links and the fields e.g. profile_background_color that users can customize their profiles?
Have one single User class with everything.
class User {
String profile_big_url
String profile_thumb_url
String profile_background_color
String profile_text_color
String profile_link_color
String profile_sidebar_fill_color
String profile_sidebar_border_color
String profile_background_image_url
String profile_background_tile
}
Or three classes
class User{
Photo photo
Profile profile
}
class Photo{
User user
String profile_big_url
String profile_thumb_url
}
class Profile{
User user
String profile_background_color
String profile_text_color
String profile_link_color
String profile_sidebar_fill_color
String profile_sidebar_border_color
String profile_background_image_url
String profile_background_tile
}
Which is better regarding scale, performance, modification?
I wouldn't worry about it. Splitting the tables results in smaller selects but these are just short strings, so the cost of pulling in more data than you need is minor. Joins can be expensive, but again, these would be simple ones.
An alternative would be to leave everything in one table, but split the class logically into three just in the code, using components. See http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html#5.2.2%20Composition%20in%20GORM

Resources