How to setItems in vaadin grid when items are in a map - java

I am trying to load use this query and the values into a map
LinkedHashMap<SCRegionPriority, String> hash = new LinkedHashMap<>();
pstmt=("SELECT a.Id,a.RegionName,ISNULL(b.Priority,0) as priority
FROM dbo.region a left join dbo.SCMap b on a.Id = b.RegionId
and a.CountryId = b.CountryId and b.SCId=1 where a.CountryId ='1'")
ResultSet rs = pstmt.executeQuery();
con.commit();
while (rs.next()) {
SCPri c = new SCPri();
c.setRegionid(rs.getInt(1));
c.setRegionname(rs.getString(2));
c.setPriority(rs.getInt(3));
hash.put(c, String.valueOf(rs.getInt(3)));
}
the query gives me the following values:
1,0|2,1|3,1|4,2|...
And then I am trying to load this into the vaadin grid like the following:
List<HashMap<SCPri, String>> rows = new ArrayList<>();
LinkedHashMap<SCPri, String> fakeBean1 = subdao1.getSCMap(subcontractor.getId(),subcontractor.getCountryId());
rows.add(fakeBean1);
Grid<HashMap<SCPri, String>> grid2 = new Grid<>();
grid2.setItems(rows);
for (Map.Entry<SCPri, String> entry : s.entrySet()) {
grid2.addColumn(h -> h.get(entry.getKey().getRegionname())).setCaption(entry.getKey().getRegionname());
}
addComponents(grid2);
I am not able to load the grid with the columns dynamically generated and one editable row of with values underneath those columns.
I am trying to make the grid look like the following:
r1|r2|r3|r4
0 |1 |1 |2
I tried to follow the following two links but failed to get it working:
How to fill Vaadin Grid with Map items type
https://vaadin.com/forum/thread/16038356/grid-8-without-bean-class
How can I achieve this?

A single row with empty cells implies that the value provider callback for each cell returns null (or "").
In your case, the value provider callback is h -> h.get(entry.getKey().getRegionname()). Here, h represents the row object, i.e. your single HashMap<SCPri, String> instance. I'm assuming getRegionname() returns something like a String, which would surely cause null results from h.get() since h uses SCPri instances as they key. Changing the callback to h -> h.get(entry.getKey()) instead might do the trick.
It is an unfortunate leftover from the pre-generics times that Map::get accepts any Object without compilation errors instead of requiring you to pass an instance of the actual key type of the map.

Related

MongoTemplate database query, instead of in-service code, to get required data

I need to create a mongotemplate database query to get a specific number of elements into a list.
At the moment I just get all the elements with findAll(), and then I modify the obtained data using code that I have writen within the service class.
Initially, I have a Laptop class with fields price::BigDecimal and name::String and I use findAll() to get a list of them.
Then I put those in a HashMap, where key is the name field, sorted from most expensive to cheapest.
Map<String, List<Laptop>> laptopsMap = laptopsFrom.stream()
.collect(Collectors.groupingBy(Laptop::getName,
Collectors.collectingAndThen(Collectors.toList(),
l -> l.stream()
.sorted(Comparator.comparing(Laptop::getPrice).reversed())
.collect(Collectors.toList())
))
);
So the results are like below:
[{"MSI", [2200, 1100, 900]},
{"HP", [3200, 900, 800]},
{"Dell", [2500, 2000, 700]}]
Then, I use the code in the bottom of the question, to create a Laptop list with the following contents:
[{"HP", 3200}, {"Dell", 2500}, {"MSI", 2200},
{"Dell", 2000}, {"MSI", 1100}, {"HP", 900},
{"MSI", 900}, {"HP", 800}, {"Dell", 700}]
So basically, I iterate the map and from each key, I extract the next in line element of the list.
do {
for (Map.Entry<String, List<Laptop>> entry :
laptopsMap.entrySet()) {
String key = entry.getKey();
List<Laptop> value = entry.getValue();
finalResultsList.add(value.get(0));
value.remove(0);
if (value.size() == 0) {
laptopsMap.entrySet()
.removeIf(pr -> pr.getKey().equals(key));
} else {
laptopsMap.replace(key, value);
}
}
} while(!laptopsMap.isEmpty());
I instead of all this in-class code need to use a mongoTemplate database argument, but I cant seem to figure out how to create such a complex query. I have read material about Aggregation but I have not found anything helpful enough. At the moment, I have started putting a query together as shown below:
Query query = new Query();
query.limit(numOfLaptops);
query.addCriteria(Criteria.where(Laptop.PRICE).gte(minPrice));

Getting NoFastSuchElementException, when I use valueMap() in gremlin query with java

GraphTraversal<Vertex, Map<String, Object>> tsList = traversalSource.V().has("request","id_key",114).valueMap();
while(tsList.hasNext())
{
System.out.println(tsList.next().get("status")); //prints result
System.out.println(tsList.next().get("tree_id_key")); //prints result
System.out.println(tsList.next().get("username")); //here throws Exception for any vertex.
System.out.println(tsList.next().get("tree_status"));
}
when I run the above query, I am getting values for any first and second propertyKey. but after getting answers for two Keys It throws NoFastSuchElementException for any propertyKey...Kindly help me..how can I resolve this?
but using below query I am able to get the answer:
GraphTraversal<Vertex, Map<String, Object>> tsList = traversalSource.V().has("request","id_key",114).values("status","tree_id_key","username","tree_status");
while(tsList.hasNext())
{
System.out.println(tsList.next());//prints "status" value
System.out.println(tsList.next());//prints "tree_id_key" value
System.out.println(tsList.next());//prints "username" value
System.out.println(tsList.next());//prints "tree_status" value
}
updated:
GraphTraversal<Vertex, Map<String, Object>> ts = traversalSource.V().has("request","id_key",113).valueMap();
while(ts.hasNext())
{
Map<String, Object> tsList=ts.next();
SuiteIdKey=(long)((ArrayList)tsList.get("suiteKey")).get(0);
seqe=(int)((ArrayList)tsList.get("sequence")).get(0);
}
In the above query, ts will return many rows and for each row I will get suiteIdkey,seqe..I am able to get the answer. But tsList is Map<>, it is not directly returning answer when I use like this =(long)tsList.get("suiteKey"), without ArrayList. Is it the correct way? Kindly help me.
You are asking for two different things in those two traversals. The first one with valueMap() asks that the vertex be converted to a Map, so you don't want to keep calling next() in that loop. Just do:
Map<String, List<Object>> m = traversalSource.V().has("request", "id_key", 114).
valueMap().next();
System.out.println(m.get("status").get(0));
System.out.println(m.get("tree_id_key").get(0));
System.out.println(m.get("username").get(0));
System.out.println(m.get("tree_status").get(0));
Keep in mind above that i'm assuming your traversal always returns one vertex...account for that otherwise if that is not true.
In your second traversal where you do values() you are asking Gremlin to convert grab the values of those specific properties on that vertex and stream them out and thus you need to iterate with multiple calls to next.
Note that typically returning the entire vertex object isn't a recommended practice. It is somewhat akin to SELECT * FROM table in SQL. It is better to get only the fields that you want to get which then gets rid of the ugly multi-property issue of Map<String, List<Object>>:
Map<String, Object> m = traversalSource.V().has("request", "id_key", 114).
project('s`,'tik', 'u', 'ts').
by('status').
by('tree_id_key').
by('username')
by('tree_status').
next();
System.out.println(m.get("s"));
System.out.println(m.get("tik"));
System.out.println(m.get("u"));
System.out.println(m.get("ts"));

Batchload items form a DynamoDB table using gloabalSecondaryIndex(GSI)

I have a DynamoDB table having field X as a GSI hash key, I what query this table to fetch all documents where the field X has value contained in the list xList = ["a", "b", "c"]. what is the best way to query this using DynamoDBMapper?
Right now I use the following code for this senario,
List<TableDoc> tableDocs = xList.stream().map( x -> new TableDocument().setX(x)).collect(Collectors.toList());
List<String, List<Object>> result = dynamoDBMapper.batchLoad(tableDocs);
I have documents in the table corresponding to the x values in xList, But I get null when I do
result.get(TABLE_NAME);
Is this a right way of batchloading items using GSIs?
Thanks for reading :)

AWS DynamoDB multiple "NE" string filters?

I'm trying to scan/query an AWS DynamoDB table for a list of items where id (a single string) is not equal to any of strings A, B, C, D, etc.
I've tried something like this:
for (String itemString : items) {
scanExpression.addFilterCondition("id",
new Condition().withComparisonOperator(ComparisonOperator.NE)
.withAttributeValueList(new AttributeValue().withS(itemString)));
}
PaginatedScanList<Items> result = mapper.scan(Item.class, scanExpression);
What appears to happen is that each time I add filter, it overwrites the previous values, so that the scan only checks against one itemString, not several. Am I missing something, or is this a limitation of DynamoDB?
Note: if it matters, in my example, I listed four values (A, B, C, D) but in production, this may be a list of hundreds of values.
You are correct in saying that the way you are doing it "overwrites the previous values". Here is the relevant code from the 1.9.23 SDK on DynamoDBScanExpression:
public void addFilterCondition(String attributeName, Condition condition) {
if ( scanFilter == null )
scanFilter = new HashMap<String, Condition>();
scanFilter.put(attributeName, condition);
}
Since your attributeName will be id for both puts, the last value will win in this case.
In my opinion, this is poor behavior from DynamoDBScanExpression, and I would even lean more towards saying it is a bug that should be reported. The documentation does not state anything about when a duplicate attributeName is added and the method name makes it seem like this is unexpected behavior.
I don't see a good way to work around this other than building out the entire filter expression.
Another Note: On the documentation, I don't see a length constraint for how long a filter expression can be as well as how many ExpressionAttributeNames and ExpressionAttributeValues are allowed on a request. That may come into account if you are trying to filter out a ton of attribute values, but I haven't found any documentation of what that limit might be or what behavior you should expect.
StringJoiner filterExpression = new StringJoiner(" AND ");
Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
int itemAttributeSuffix = 0;
for (String itemString : items) {
StringBuilder expression = new StringBuilder("#idname")
.append(" ")
.append("<>")
.append(" ")
.append(":idval")
.append(itemAttributeSuffix);
filterExpression.add(expression);
expressionAttributeValues.put(":idval" + itemAttributeSuffix++,
new AttributeValue().withS(itemString));
}
Map<String, String> expressionAttributeNames = Collections.singletonMap("#idname", "id");
scanExpression.setFilterExpression(filterExpression.toString());
scanExpression.setExpressionAttributeNames(expressionAttributeNames);
scanExpression.setExpressionAttributeValues(expressionAttributeValues);
PaginatedScanList<Items> result = mapper.scan(Item.class, scanExpression);

Java remove duplicate values from result set

I have requirement to remove the duplicate values from result set based on some unique identifier.
I need to remove the duplicates from the result set.
while(resultSet.next())
{
int seqNo = resultSet.getInt("SEQUENCE_NO");
String tableName = resultSet.getString("TABLE_NAME");
String columnName = resultSet.getString("COLUMN_NAME");
String filter = resultSet.getString("FILTER");
}
from the above iteration, i m getting 2 rows from result set. There is same seq no,same table name, different columnname, same filter.
1 PRODUCTFEES CHARGETYPE PRODUCTID
1 PRODUCTFEES PRODUCTCODE PRODUCTID
My requirement is to remove the duplicate table name, duplicate seq no, duplicate filter.
I want to get output something below,
1 PRODUCTFEES CHARGETYPE PRODUCTCODE PRODUCTID
By the example you provide, it seems like you want to output all distinct values for each column indidivually (there are 4 columns in the table, but you output 5 values).
Being the question tagged java, an approach you could take would be using an implementation of Set for each of the columns, so that duplicates won't get through. Then output all the elements of each Set.
LinkedHashSet[] sets = new LinkedHashSet[]{
new LinkedHashSet(),
new LinkedHashSet(),
new LinkedHashSet(),
new LinkedHashSet() };
while(resultSet.next()) {
sets[0].add(resultSet.getInt("SEQUENCE_NO"));
sets[1].add(resultSet.getString("TABLE_NAME")););
sets[2].add(resultSet.getString("COLUMN_NAME"));
sets[3].add(resultSet.getString("FILTER"));
}
StringBuilder buf = new StringBuilder();
for (LinkedHashSet set : sets) {
// append to buf all elements of each set
}
But it might be simpler to address this from the very same SQL query and just make SELECT DISTINCT columnX for each of the columns and output the result without further manipulation. Or use an aggregation function that will concatenate all distinct values. The implementation will be highly dependent on the DBMS you're using (GROUP_CONCAT for MySQL, LISTAGG for Oracle, ...). This would be a similar question for Oracle: How to use Oracle's LISTAGG function with a unique filter?
Based on the different outputs I'd say, that you not just need to remove duplicates, but also reorder the data from the duplicates.
In that case you need to fill a new data-array (or similar structure) in the while(resultSet.next()), and after that loop over the newly arranged data-object and output accordingly.
In Meta-Lang this would be as follows:
while resultset.next()
if newdata-array has unique key
add column-name to found entry in newdata-array
else
create new entry in newdata-array with column-name
while newdata-array.next()
output seq, table-name
while entry.column-names.next()
output column-name
output product-id

Categories

Resources