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
Related
I am looking for some solution where i want to pass 100s of records to the form where i am having more than 50 fields. I did some research for the testNG data providers but it looks like that it returns only strings so i feel that it will not be feasible to go with data providers as if its not good to pass 50 string arguments to specific function. Also i did some research to read excel file and i get two ways that either i can go with the jxl or Apache poi but with that also i am not able to read the data by the column header as if i can not go with the row and column number of approach as i have so many fields that i need to work with. The reason behind that is that in future is one field has added to single form that its going to be rework and again its not feasible.
enter image description here
I have been following this link:
http://www.softwaretestinghelp.com/selenium-framework-design-selenium-tutorial-21/
for reading data column wise but any how i am not getting the records based on the column header. Do we have any other way to achieve this.
Thanks
"testNG data providers but it looks like that it returns only strings" - incorrect. It allows you to return a multidimensional array of type Object. What kind of object you create is your own code. You may choose to read from the excel, encapsulate all the fields in one object (your own pojo) or multiple objects and then the method argument can have just those object types declared and not the 50 strings.
Both jxl and poi are libraries to interact with excel. If you want to have specific interaction with excel, like reading based on header, then you need to write code for that - it doesn't come out of the box.
If you are concerned about addition of one more column , then build your indices first by reading the header column, then put it in a relevant data structure and then go about reading your data.
I finally achieved that with the help of apache poi. I created on centralized function that is returning the hashmap having title as an index.
Here is that function:
Here is my main test function:
#Test(dataProvider="dpCreateNewCust")
public void createNewCustomer(List<Map<String, String>> sheetList){
try{
//Step 2. Login
UtilityMethods.SignIn();
for(Map<String, String> map : sheetList){
//Step 3. New Customer
if(map.get("Testcase").equals("Yes"))
{
//Process with excel data
ProcessNewCustomer(map);
}
}
}
catch(InterruptedException e)
{
System.out.println ("Login Exception Raised: <br> The exception get caught" + e);
}
}
//My data provider
#DataProvider(name = "dpCreateNewCust")
public Object[][] dpCreateNewCust(){
XLSfilename = System.getProperty("user.dir")+"//src//watts//XLSFiles//testcust.xlsx";
List<Map<String, String>> arrayObject = UtilityMethods.getXLSData(XLSfilename,Sheetname));
return new Object[][] { {arrayObject } };
}
//----GetXLSData Method in UtilityMethods Class :
public static List<Map<String, String>> getXLSData(String filename, String sheetname)
{
List<String> titleList = new ArrayList<String>();
List<Map<String, String>> sheetList = new ArrayList<Map<String, String>>();
try {
FileInputStream file = new FileInputStream(filename);
//Get the workbook instance for XLS file
XSSFWorkbook XLSbook = new XSSFWorkbook(file);
//Get first sheet from the workbook
//HSSFSheet sheet = workbook.getSheetAt(0);
WorkSheet = XLSbook.getSheet(sheetname);
//Iterate through each rows from first sheet
int i = 0;
Iterator<Row> rowIterator = WorkSheet.iterator();
while(rowIterator.hasNext()) {
Row row = rowIterator.next();
//For each row, iterate through each columns
Iterator<Cell> cellIterator = row.cellIterator();
int j = 0;
Map<String, String> valueMap = new HashMap<>();
while(cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if(i==0){
titleList.add(cell.getStringCellValue());
}
else
{
String cellval = "";
switch(cell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
cellval = cell.getBooleanCellValue()+"";
break;
case Cell.CELL_TYPE_NUMERIC:
cellval = String.valueOf(cell.getNumericCellValue())+"";
break;
case Cell.CELL_TYPE_STRING:
cellval = cell.getStringCellValue();
break;
default:
break;
}
if(cellval!="")
{
valueMap.put(titleList.get(j), cellval); valueMap.put("ResultRow",String.valueOf(row.getRowNum()));
valueMap.put("ResultCol",String.valueOf(0));
}
}
j++;
}
if(i!=0 && !valueMap.isEmpty()){
//System.out.println(valueMap);
sheetList.add(valueMap);
}
i++;
}
//System.out.println(sheetList); System.exit(0);
file.close();
XLSbook.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sheetList;
}
I am scratching my head here. I have a bootstrap modal that has a field for entering in a sql query. The query I pass uses an AJAX call to a controller and executes the sql query using the code below and returns a JSON object. Something like this:
context.Database.SqlQuery(typeof(object), query);
But all I get are empty objects. I can't pass a type when I don't know the columns. For instance I could do something like this:
public class CusType {
public CusType(){}
public int Id { get; set; }
public string Name { get; set; }
}
and then do something like this:
context.Database.SqlQuery(typeof(CusType), query);
But that won't help me when I don't know or can't know the columns. I even tried an idea using ExpandoObjects. Example:
List<string> columns = new List<string>();
string tmpCol = query;
string[] seperator = new string[] { "from" };
tmpCol = query.ToLower()
.Replace(#"\s+", "")
.Replace("select", "");
tmpCol = tmpCol.Split(seperator, 1, StringSplitOptions.RemoveEmptyEntries)[0];
for (int i = 0; i < tmpCol.Split(',').Length; i++)
{
columns.Add(tmpCol.Split(',')[i]);
}
dynamic data = new ExpandoObject();
IDictionary<string, object> props = (IDictionary<string, object>)data;
foreach (var column in columns)
{
props.Add(column.ToString(), column.ToString());
}
return context.Database.SqlQuery(data.GetType(), query);
But what do I do when I want to execute the query?
context.Database.SqlQuery(data.GetType()??, query);
Even when I do put in the data.GetType() it returns empty objects.
In both examples (using typeof(object) and typeof(data.GetType()) I get this JSON object returned:
[{},{},{},{},{},{},{},{},{},{},{},{},{}]
Any ideas/suggestions?
Entity Framework populates a model based on the type specified. You'll need to use something else or go old school with a DataReader.
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 am writing a client-server java FX application with a table View. I have a database in the server side and I want from the Client to load the table Columns and table Records from the db to a table View dynamically. So far I have found many hints, on how to do this successfully. The thing is that I want to add to the table a column 'select' which is a check box. Below is my code.
private void AddToTableRecordsFromDB(TabPane tp){
tableview = (TableView) tp.lookup("#table");
ObservableList<Object> data = null;
try {
String[] columnNames = (String[]) Login.Login.in.readObject();
ArrayList<ArrayList> al = (ArrayList<ArrayList>) Login.Login.in.readObject();
/**********************************
* TABLE COLUMN ADDED DYNAMICALLY *
**********************************/
TableColumn select = new TableColumn("Select");
select.setCellValueFactory(new PropertyValueFactory("invited"));
select.setCellFactory(new Callback<TableColumn<ObservableValue, Boolean>, TableCell<ObservableValue, Boolean>>() {
public TableCell<ObservableValue, Boolean> call(TableColumn<ObservableValue, Boolean> p) {
return new CheckBoxTableCell<ObservableValue, Boolean>();
}
});
tableview.getColumns().add(select);
for(int i=0 ; i<columnNames.length; i++){
//use non property style for making dynamic table
final int j = i;
TableColumn col;
col = new TableColumn(columnNames[i]);
col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList,String>,ObservableValue<String>>(){
#Override
public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {
return new SimpleStringProperty(param.getValue().get(j).toString());
}
});
tableview.getColumns().add(col);
}
/********************************
* Data added to ObservableList *
********************************/
data = FXCollections.observableArrayList();
for(int i=0 ; i<al.size(); i++){
ObservableList<ArrayList> row = FXCollections.observableArrayList(al.get(i));
data.add(row);
}
//FINALLY ADDED TO TableView
tableview.setItems(data);
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Developer_Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
I took the CheckBoxTableCell class from the JavaFX2.0 Ensemble.
The database loads successfully in to the table view and also my 'select' column is created, but I can not see any check boxes in the rows.
Any help please ?
You say you are using "non property style" to add columns dynamically, and your table view made of list of list items. I guess there is no getInvited() method in those data structure model. However by setting select.setCellValueFactory(new PropertyValueFactory("invited")); the table column will look for that method. Set cell value factory with valid value.
EDIT: I didn't test but can you try the code below.
select.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList, String>, ObservableValue<String>>() {
public ObservableValue<String> call(TableColumn.CellDataFeatures<ObservableList, String> p) {
return new SimpleStringProperty(p.getValue().get(0).toString());
}
});
Note the get(0). Namely it would be better if readObject() returns at least 1 item. Another note is CheckBoxTableCell needs a Callback which returns ObservableProperty<Boolean> and binds bidirectionally so I think it is better to implement your own cell factory containing checkbox, regarding to your data model.
I was going through the SOQL documentation , but couldn't find query to fetch all the field data of an entity say , Account , like
select * from Account [ SQL syntax ]
Is there a syntax like the above in SOQL to fetch all the data of account , or the only way is to list all the fields ( though there are lot of fields to be queried )
Create a map like this:
Map<String, Schema.SObjectField> fldObjMap = schema.SObjectType.Account.fields.getMap();
List<Schema.SObjectField> fldObjMapValues = fldObjMap.values();
Then you can iterate through fldObjMapValues to create a SOQL query string:
String theQuery = 'SELECT ';
for(Schema.SObjectField s : fldObjMapValues)
{
String theLabel = s.getDescribe().getLabel(); // Perhaps store this in another map
String theName = s.getDescribe().getName();
String theType = s.getDescribe().getType(); // Perhaps store this in another map
// Continue building your dynamic query string
theQuery += theName + ',';
}
// Trim last comma
theQuery = theQuery.subString(0, theQuery.length() - 1);
// Finalize query string
theQuery += ' FROM Account WHERE ... AND ... LIMIT ...';
// Make your dynamic call
Account[] accounts = Database.query(theQuery);
superfell is correct, there is no way to directly do a SELECT *. However, this little code recipe will work (well, I haven't tested it but I think it looks ok). Understandably Force.com wants a multi-tenant architecture where resources are only provisioned as explicitly needed - not easily by doing SELECT * when usually only a subset of fields are actually needed.
You have to specify the fields, if you want to build something dynamic the describeSObject call returns the metadata about all the fields for an object, so you can build the query from that.
I use the Force.com Explorer and within the schema filter you can click the checkbox next to the TableName and it will select all the fields and insert into your query window - I use this as a shortcut to typeing it all out - just copy and paste from the query window. Hope this helps.
In case anyone was looking for a C# approach, I was able to use reflection and come up with the following:
public IEnumerable<String> GetColumnsFor<T>()
{
return typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.Where(x => !Attribute.IsDefined(x, typeof(System.Xml.Serialization.XmlIgnoreAttribute))) // Exclude the ignored properties
.Where(x => x.DeclaringType != typeof(sObject)) // & Exclude inherited sObject propert(y/ies)
.Where(x => x.PropertyType.Namespace != typeof(Account).Namespace) // & Exclude properties storing references to other objects
.Select(x => x.Name);
}
It appears to work for the objects I've tested (and matches the columns generated by the API test). From there, it's about creating the query:
/* assume: this.server = new sForceService(); */
public IEnumerable<T> QueryAll<T>(params String[] columns)
where T : sObject
{
String soql = String.Format("SELECT {0} FROM {1}",
String.Join(", ", GetColumnsFor<T>()),
typeof(T).Name
);
this.service.QueryOptionsValue = new QueryOptions
{
batchsize = 250,
batchSizeSpecified = true
};
ICollection<T> results = new HashSet<T>();
try
{
Boolean done = false;
QueryResult queryResult = this.service.queryAll(soql);
while (!finished)
{
sObject[] records = queryResult.records;
foreach (sObject record in records)
{
T entity = entity as T;
if (entity != null)
{
results.Add(entity);
}
}
done &= queryResult.done;
if (!done)
{
queryResult = this.service.queryMode(queryResult.queryLocator);
}
}
}
catch (Exception ex)
{
throw; // your exception handling
}
return results;
}
For me it was the first time with Salesforce today and I came up with this in Java:
/**
* #param o any class that extends {#link SObject}, f.ex. Opportunity.class
* #return a list of all the objects of this type
*/
#SuppressWarnings("unchecked")
public <O extends SObject> List<O> getAll(Class<O> o) throws Exception {
// get the objectName; for example "Opportunity"
String objectName= o.getSimpleName();
// this will give us all the possible fields of this type of object
DescribeSObjectResult describeSObject = connection.describeSObject(objectName);
// making the query
String query = "SELECT ";
for (Field field : describeSObject.getFields()) { // add all the fields in the SELECT
query += field.getName() + ',';
}
// trim last comma
query = query.substring(0, query.length() - 1);
query += " FROM " + objectName;
SObject[] records = connection.query(query).getRecords();
List<O> result = new ArrayList<O>();
for (SObject record : records) {
result.add((O) record);
}
return result;
}
I used following to get complete records-
query_all("Select Id, Name From User_Profile__c")
To get complete fields of record, we have to mention those fields as mentioned here-
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select.htm
Hope will help you !!!