I'm using a CellTable to display entities' information stored in the Datastore. Data type of the parameters are String and int.
I decided to use SelectionCell to show the value of every parameter. This works perfectly when it comes to String data type, but it fails with int data type.
For instance, I have a parameter called:
String name;
Possible values for this parameter are: "Name1", "Name2" or "Name3". I have these values in the SelectionCell, so if an entity has a parameter name = "Name2", SelectionCell displays "Name2"
List<String> names= new ArrayList<String>();
names.add("Name1");
names.add("Name2");
names.add("Name3");
SelectionCell nameCell = new SelectionCell(names);
Column<Entity, String> nameColumn = new Column<Entity, String>(nameCell){
#Override
public String getValue(Entity object){
return object.getName();
}
};
cellTable.addColumn(nameColumn, "Name");
Now, I have a parameter called:
int age;
Possible values for this parameter are: 18, 19, 20,... ,65. I have these values in the SelectionCell, but if an entity has a parameter age = 25, SelectionCell doesn't display that value, it displays 18.
List<String> ages= new ArrayList<String>();
for(int i = 18; i <= 65; i++){
ages.add("" + i);
}
SelectionCell ageCell = new SelectionCell(ages);
Column<Entity, String> ageColumn = new Column<Entity, String>(ageCell){
#Override
public String getValue(Entity object){
return "" + object.getAge();
}
};
cellTable.addColumn(ageColumn, "Age");
How can I solve that?
Cheers.
Try Creating your List of Ages before creating the dataGrid.
Related
I have a class in which I get the number of ids per year with a soql query on a custom object:
public static Integer numberRecords(Integer year) {
List<AggregateResult> numbersOfRecords = [
SELECT Keeper__c
FROM Month_Expense_Application__c
WHERE calendar_year(MonthDate__c) =: year
];
Set<Id> keepers = new Set<Id>();
for (AggregateResult result : numbersOfRecords) {
keepers.add((Id)result.get('Keeper__c'));
}
Integer value = keepers.size();
return value;
}
I'm trying to write a test for this method by creating an object and filling in the fields it needs, then I try to get the id with a soql request and compare:
#isTest
public class ExpenseAdminControllerTests {
#isTest
public static void numberRecordsTests() {
Month_Expense_Application__c monthExpenseTest = new Month_Expense_Application__c(
Balance__c = 12.3,
Income__c = 11,
Keeper__c = '0034x00001K7kGCAAZ',
MonthDate__c = date.newInstance(2022, 11, 21)
);
Integer year = 2022;
List<Month_Expense_Application__c> numbersOfRecords = [
SELECT Keeper__c
FROM Month_Expense_Application__c
WHERE calendar_year(MonthDate__c) =: year AND Id =: monthExpenseTest.Id
];
Set<Id> keepers = new Set<Id>();
keepers.add(numbersOfRecords[0].Keeper__c);
Integer value = keepers.size();
System.assertEquals(1, value);
}
}
But i cant tell me what am i doing wrong
I guess you just forgot to insert "monthExpenseTest" in actual database, by means that you have just created a object by using below lines as you mentioned
Month_Expense_Application__c monthExpenseTest = new Month_Expense_Application__c(
Balance__c = 12.3,
Income__c = 11,
Keeper__c = '0034x00001K7kGCAAZ',
MonthDate__c = date.newInstance(2022, 11, 21)
);
by writing above lines you just created object which is present in memory only. it is not stored in database, so that it is not fetched when you try to fetch it via SOQL Query.
Now you may want to add one more line after above code.which is given as below
insert monthExpenseTest ;
so after inserting your object is stored in database. now you can fetch it via SOQL query.
So your test class will be looks like below
#isTest
public class ExpenseAdminControllerTests {
#isTest
public static void numberRecordsTests() {
Month_Expense_Application__c monthExpenseTest = new Month_Expense_Application__c(
Balance__c = 12.3,
Income__c = 11,
Keeper__c = '0034x00001K7kGCAAZ',
MonthDate__c = date.newInstance(2022, 11, 21)
);
insert monthExpenseTest;
Integer year = 2022;
Integer keepers = ExpenseAdminController.numberRecords(year);
System.assertEquals(1, keepers);
}
}
So when you are testing ExpenseAdminController then you just need to call that method because you want to test it. in test class which is mentioned in question it not testing numberRecords() method instead of you are rewriting logic.
I want to take "ids" and assign it to an arraylist. config.json file is here:
{
"users":[
{"user id":1,"user name":"A","user type":"bot1", "ids": [1 ,2]},
{"user id":2,"user name":"B","user type":"bot2","ids": [1 ,2]},
{"user id":3,"user name":"C","user type":"bot3","ids": [2 ,3]}
]
}
To read this json file I have tried this:
JSONArray jsonArrayForUsers = (JSONArray) jsonObject.get("users");
for (int i=0; i<jsonArrayForUsers.size(); i++) {
JSONObject obj2 = (JSONObject) jsonArrayForUsers.get(i);
long userId = (long) obj2.get("user id");
String userName = (String) obj2.get("user name");
String userType = (String) obj2.get("user type");
JSONArray jsonDatasetIds = (JSONArray) jsonObject.get("ids");
List <Integer> list = Arrays.asList(jsonDatasetIds);// Trying to covert JSONArray into an array but error occurs
//Type mismatch: cannot convert from List<JSONArray> to List<Integer>
users.add(new User((int)userId, userName, userType,list));
}
I could read "user id", "user name" , "user type" correctly. But I don't know how to read -"ids": [1 ,2]- part and create an arraylist from it.
Edit:
Problem solved after I've changed
//It should've been 'obj2.get()'
JSONArray jsonDatasetIds = (JSONArray) obj2.get("ids");
for(int a = 0; i<jsonDatasetIds.size();i++){
list.add((int)jsonDatasetIds.get(a));
}
users.add(new User((int)userId, userName, userType,list));
But now I can not add values from 'jsonDatasetIds' to 'list'.
In other words I can not take values from JSONArray.
There are many ways to improve the code, let's start by reformulating the problem: You need to go from a JSON string to a model object with all the attributes mapped.
There are good libraries for doing just this, like Jackson and Gson, but it can also be done with json-simple 1.1.1 as you are doing.
Assuming your model object looks like this:
public class User {
private int id;
private String name;
private String type;
private List<Integer> ids;
// and constructor + getters + setters
}
And starting from the JSON you provided:
{
"users":[
{"user id":1, "user name":"A", "user type":"bot1", "ids":[1, 2]},
{"user id":2, "user name":"B", "user type":"bot2", "ids":[1, 2]},
{"user id":3, "user name":"C", "user type":"bot3", "ids":[2, 3]}
]
}
We can make a first attempt that looks like this:
public static void main(String[] args) throws ParseException {
String json =
"{ \"users\":[" +
" {\"user id\":1,\"user name\":\"A\",\"user type\":\"bot1\", \"ids\": [1 ,2]}," +
" {\"user id\":2,\"user name\":\"B\",\"user type\":\"bot2\",\"ids\": [1 ,2]}," +
" {\"user id\":3,\"user name\":\"C\",\"user type\":\"bot3\",\"ids\": [2 ,3]}" +
" ]" +
"}";
List<User> result = new ArrayList<>();
JSONParser parser = new JSONParser();
JSONObject root = (JSONObject) parser.parse(json);
List<JSONObject> users = (List<JSONObject>) root.get("users");
for (JSONObject user: users) {
List<Integer> userIds = new ArrayList<>();
for (Long id : (List<Long>) user.get("ids")) {
userIds.add(id.intValue());
}
result.add(new User(((Long)user.get("user id")).intValue(), (String) user.get("user name"), (String) user.get("user type"), userIds));
}
System.out.println(result);
}
As you can see a JSONArray can be directly casted to a List, and if we look at the signature of JSONArray class we can understand why:
public class JSONArray extends ArrayList implements List, JSONAware, JSONStreamAware
JSONArray is actually extending ArrayList so you do not need to create a new one and that is why the line List<JSONObject> users = (List<JSONObject>) root.get("users"); works.
Now that you have a list its possible to iterate over the elements with the usual foreach loop for (JSONObject user: users) {...} and process each element.
For the internal "ids" we could do the same thing but from your code it seems the ids must be integers and json-simple returns Long objects, so we need to convert them and that is why the second loop is there (if the model object accepted a List<Long> it would not be needed).
A different way for doing the same thing is with java 8 streams, specifying the different steps you need to convert the source object into the destination one:
public static void main(String[] args) throws ParseException {
String json =
"{ \"users\":[" +
" {\"user id\":1,\"user name\":\"A\",\"user type\":\"bot1\", \"ids\": [1 ,2]}," +
" {\"user id\":2,\"user name\":\"B\",\"user type\":\"bot2\",\"ids\": [1 ,2]}," +
" {\"user id\":3,\"user name\":\"C\",\"user type\":\"bot3\",\"ids\": [2 ,3]}" +
" ]" +
"}";
JSONParser parser = new JSONParser();
JSONObject root = (JSONObject) parser.parse(json);
List<User> result = ((List<JSONObject>)root.get("users"))
.stream()
.map(user -> new User(
((Long)user.get("user id")).intValue(),
(String) user.get("user name"),
(String) user.get("user type"),
((List<Long>) user.get("ids"))
.stream()
.map(Long::intValue)
.collect(Collectors.toList())))
.collect(Collectors.toList());
System.out.println(result);
}
In my opinion the stream api is more clear in situations when you need to go step by step transforming a list of objects from one type to another, in this example it does not makes much of a difference but in more complex situations with many intermediate steps it can be a really useful tool.
Earlier I had a table named ApplicationConfiguration which simply had [Key],[Value] columns to store some config data. This was queried straight away using SQL queries.
Now I intend to make use of Entity Framework (EF) Code First approach to query this table. The specialty of this table is that the table will have only a fixed number of rows in its lifetime. Only the Value column can be updated.
So as per the code first approach, we have to first write our POCO classes with its properties that will be mapped to columns in the underlying table. However, I wish to have a Dictionary<> structure to represent these configuration KV pairs. My concern is, will EF be able to fire update queries against any updation to the the value of a particular pair.
Also since I am using Code First approach, I would want some seed data(i.e the fixed number of rows and its initial content) to the added after the table itself is created on the fly when the application is first executed.
If Dictionary<> cannot be used, please suggest some alternative. Thanks in advance.
Coded this way:
public class ApplicationConfiguration
{
public int Id { get; set; }
public string Key { get; set; }
public int Value { get; set; } // should be string, but I'm lazy
}
class Context : DbContext
{
internal class ContextInitializer : DropCreateDatabaseIfModelChanges<Context>
{
protected override void Seed(Context context)
{
var defaults = new List<ApplicationConfiguration>
{
new ApplicationConfiguration {Key = "Top", Value = 5},
new ApplicationConfiguration {Key = "Bottom", Value = 7},
new ApplicationConfiguration {Key = "Left", Value = 1},
new ApplicationConfiguration {Key = "Right", Value = 3}
};
// foreach (var c in defaults)
// context.ConfigurationMap.Add(c.Key, c); // by design, no IReadOnlyDictionary.Add
foreach (var c in defaults)
context.ApplicationConfigurations.Add(c);
base.Seed(context);
}
}
public Context()
{
Database.SetInitializer(new ContextInitializer());
}
private IDbSet<ApplicationConfiguration> ApplicationConfigurations
{
get { return Set<ApplicationConfiguration>(); }
}
public IReadOnlyDictionary<string, ApplicationConfiguration> ConfigurationMap
{
get { return ApplicationConfigurations.ToDictionary(kvp => kvp.Key, kvp => kvp); }
}
}
Used this way:
using (var context = new Context())
{
ReadConfigurationOnly(context.ConfigurationMap);
}
using (var context = new Context())
{
ModifyConfiguration(context.ConfigurationMap);
context.SaveChanges();
}
static void ReadConfigurationOnly(IReadOnlyDictionary<string, ApplicationConfiguration> configuration)
{
foreach (var k in configuration.Keys)
Console.WriteLine("{0} = {1}", k, configuration[k].Value);
}
static void ModifyConfiguration(IReadOnlyDictionary<string, ApplicationConfiguration> configuration)
{
foreach (var k in configuration.Keys)
configuration[k].Value++; // this is why I was lazy, using an int for a string
}
So, I wrote it up this way — using an int Value property rather than a string — just so I could run the "Used this way" code over and over, and see the database update each time, without having to come up with some other way to change Value in an interesting way.
It's not quite as nifty here to use a IReadOnlyDictionary<string, ApplicatonConfiguration> instead of a IReadOnlyDictionary<string, string>, the way we'd really like, but that's more than made up for by the fact that we can easily modify our collection values without resorting to a clumsier Set method taking a dictionary as input. The drawback, of course, is that we have to settle for configuration[key].Value = "new value" rather than configuration[key] = "new value", but — as I say — I think it's worth it.
EDIT
Dang! I wrote this code up specifically to answer this question, but I think I like it so much, I'm going to add it to my bag of tricks ... this would fit in really well when my company goes from local databases to Azure instances in the cloud, and the current app.config has to go into the database.
Now all I need is a ContextInitializer taking a System.Configuration.ConfigurationManager as a ctor parameter in order to seed a new database from an existing app.config ...
I don't think you can map a table directly to a Dictionary; you will probably have to write your own wrapper to fill a dictionary from the table and update it back to the DB. Entities are each a row of a given table... Something like this (untested):
public Dictionary<string, string> GetDictionary()
{
Dictionary<string, string> dic = new Dictionary<string, string>();
using (var db = new Context())
{
var configs = db.ApplicationConfiguration.Select();
foreach (var entry in configs)
{
dic.Add(config.Key, config.Value);
}
}
return dic;
}
public void SaveConfig(Dictionary<string, string> dic)
{
using (var db = new Context())
{
foreach (KeyValuePair kvp in dic)
{
if (!db.ApplicationConfiguration.First(a => a.Key == kvp.Key).Value == kvp.Value)
{
var ac = new ApplicationConfiguration();
ac.Key = kvp.Key;
ac.Value = kvp.Value;
db.Entry(ac).State = EntityState.Modified;
}
}
db.SaveChanges();
}
}
For your second question, you want to use the Seed() method to add initial values to the database. See here for an example implementation.
I have a CSV file that I'd like to store as a Java object. I would like the name of the columns to be the first dimension of the array, and key pair values the second dimension of the array. I've tried different solutions (mostly LinkedHashMaps) but none seem to work properly.
The CSV looks like this:
TimeStamp;Column 1;Column 2;Column3
1385733406;Value1;Value12;Value13
1385733409;Value21;Value22;Value23
1385733411;Value31;Value32;Value33
I would like the array to look something like this:
["Column 1"]
["1385733406","Value1"]
["1385733409","Value21"]
["1385733411","Value31"]
["Column 2"]
["1385733406","Value2"]
["1385733409","Value22"]
["1385733411","Value32"]
["Column 3"]
["1385733406","Value2"]
["1385733409","Value22"]
["1385733411","Value33"]
This way, I would be able to query the object and retrieve all the key pair values from a given column, for instance, all the data from Column 1. Using HashMaps doesn't seem to work because they require two arguments, and doing this doesn't seem to be the proper way. This is the code I could come up with so far, which I don't think is the right track but it's all I could come up with. I'm using OpenJDK 1.7
public class CsvCollection {
public Map<String,Map<String,Integer>> Results = new LinkedHashMap<String, Map<String,Integer>>();
public CsvCollection(){
}
public void parseCsvResultFile(File csvFile){
CSVReader reader = null;
List myEntries = null;
try {
reader = new CSVReader(new FileReader(csvFile.getAbsolutePath()), ';');
} catch (FileNotFoundException e) {
System.out.println("Error opening [], aborting parsing");
}
try {
myEntries = reader.readAll();
} catch (IOException e) {
System.out.println("Error reading content of CSV file (but file was opened)");
}
for(String header: (String[]) myEntries.get(0)){
Results.put(header, null);
// What now?
}
}
}
You can make 2 change as follows to implements the function you needed.
1) Change the following code
public Map<String,Map<String,Integer>> Results = new LinkedHashMap<String, Map<String,Integer>>();
to
public Map<String, List<String[]>> Results = new LinkedHashMap<String, List<String[]>>();
This change is made because for a specify column, like Column 1, it has 3 rows with Timestamp and corresponding Column value. You need to use a List to store them.
2) Change the following for-loop
for(String header: (String[]) myEntries.get(0)){
Results.put(header, null);
// What now?
}
to
String[] headerColumns = (String[]) myEntries.get(0);
// First column is TimeStamp, skip it
for (int i = 1; i < headerColumns.length; i++) {
List<String[]> list = new ArrayList<String[]>();
for (int rowIndex = 1; rowIndex < myEntries.size(); rowIndex++) {
String[] row = (String[]) myEntries.get(rowIndex);
list.add(new String[] { row[0], row[i] });
}
Results.put(headerColumns[i], list);
}
With the above 2 changes, if you print the Results (type of Map< String, List< String[] > >) in console using the following code,
for(Map.Entry<String, List<String[]>> entry : Results.entrySet())
{
System.out.printf("[%s]\n",entry.getKey());
for(String[] array : entry.getValue())
{
System.out.println(Arrays.toString(array));
}
}
you will get the result you need:
[Column 1]
[1385733406, Value1]
[1385733409, Value21]
[1385733411, Value31]
[Column 2]
[1385733406, Value12]
[1385733409, Value22]
[1385733411, Value32]
[Column3]
[1385733406, Value13]
[1385733409, Value23]
[1385733411, Value33]
Note: the above example is executed using the content from a CSV file below:
TimeStamp;Column 1;Column 2;Column3
1385733406;Value1;Value12;Value13
1385733409;Value21;Value22;Value23
1385733411;Value31;Value32;Value33
Please help!!
What is the correct way to send List of String as a parameter to webservice ?
List < SObject > ObjectContents; // {get; set;} contains records of selected object
List str3 = new List ();
String FormattedValue;
for (SObject a : for (SObject a : ObjectContents)) // for (SObject a : ObjectContents)
{
for(String field:fieldApis){ // fieldApis contains list of fieldnames
FormattedValue = '\'' + a.get(field) + '\'' ; //fetches value of each field
}
str3.add(FormattedValue );
}
//sending data to webservice
sqlArray19.ArrayOfstring a= new sqlArray19.ArrayOfstring();
SQLServerConnector9.BasicHttpBinding_IService1 stub = new SQLServerConnector9.BasicHttpBinding_IService1();
//sqlArray19 and SQLServerConnector9 classes were formed while importing wsdl into Salesforce
List<String> insertMsg = stub.InsertQuery(str3); // getting error in this line
"Compile Error: Method does not exist or incorrect signature: [SQLServerConnector9.BasicHttpBinding_IService1].InsertQuery(LIST<String>)"
.net webservice which will fetch values from Salesforce and return those values
public List<String> InsertQuery(List<String> Values)
{
return Values ;
}
Collections can be troublesome data types when working across platforms with web services. Try converting your List into a string[] (and changing your method, of course).