How do I convert all TaskStatusConstant interface items into one List<String> automatically?
public interface TaskStatusConstant {
final static String NEW = "New";
final static String ACCEPTED = "Accepted";
final static String REJECTED = "Rejected";
final static String REASSIGNED = "Reassigned";
final static String COMPLETED = "Completed";
}
Those information should be represented in an enumeration.
public enum TaskStatusConstant {
NEW,
ACCEPTED,
REJECTED,
REASSIGNED,
COMPLETED
}
To iterate over an enum in Java use this:
for (TaskStatusConstant task: TaskStatusConstant.values()) {
// do what you want
}
You can use reflection, for example:
List<String> constants = new ArrayList<String>();
Field[] fields = TaskStatusConstant.class.getFields();
for (Field field : fields) {
if (field.getType().equals(String.class)) {
constants.add(field.getName());
}
}
for (String constant : constants) {
System.out.println(constant);
}
public enum TaskStatusConstant2 {
NEW("New"), ACCEPTED("Accepted"), REJECTED("Rejected"), REASSIGNED("Reassigned"), COMPLETED("Completed");
private String value;
private TaskStatusConstant2(String value) {
this.value = value;
}
public String getStatus() {
return value;
}
}
Just tried this one... Not sure this will work for my other codes :)
Using enum (recommended, has many benefits)
public enum TaskStatusConstant {
NEW("New"),
ACCEPTED("Accepted"),
REJECTED("Rejected"),
REASSIGNED("Reassigned"),
COMPLETED("Completed");
private final String toString;
private TaskStatusConstant(String toString) {
this.toString = toString;
}
#Override
public String toString() {
return toString;
}
public static List<String> valuesAsString() {
List<String> list = new ArrayList<String>();
for(TaskStatusConstant c : values()) {
list.add(c.toString());
}
return list;
}
}
Using reflection (not recommended, it's a hassle, sometimes necessary)
public static List<String> valuesAsString()
throws IllegalAccessException {
List<String> list = new ArrayList<String>();
for(Field f : TaskStatusConstant.class.getDeclaredFields()) {
if(f.getType() == String.class) {
f.setAccessible(true);
list.add((String)f.get(null));
}
}
return list;
}
Related
I want to convert the below statement result to list of my object.
import com.amazonaws.services.dynamodbv2.model.ExecuteStatementResult;
ExecuteStatementResult executeStatementResult = dynamoDB.executeStatement(executeStatementRequest);
System.out.println( executeStatementResult.getItems() );
Output:
[{bookingClasses={S: A,B,C,}, suppliers={S: BA,1A,TF,}, adjustmentType={S: PERCENTAGE,}, departureStartDate={S: 2022-11-17,}}]
Please note .getItems() method is like below:
public java.util.List<java.util.Map<String, AttributeValue>> getItems() {
return items;
}
I want something like this to work for me:
List<java.util.Map<String, AttributeValue>> items = executeStatementResult.getItems();
List<PricingRule> pricingRules = ( List<PricingRule> ) items;
Any help suggestion or workaround appreciated.
Thank you
You can't cast directly so you will need to implement something like PricingRule::fromMap and do something like
class PricingRule {
// everything you already have
public static PricingRule fromMap(Map<String, AttributeValue> items) {
// create PricingRule
}
}
Then when you need your list you can use something like
List<java.util.Map<String, AttributeValue>> items = executeStatementResult.getItems();
// assumes java 17+, alternatively use .collect(Collectors.toList())
List<PricingRule> pricingRules = items.stream().map(PricingRule::fromMap).toList();
Glad you managed to solve your problem, but have you considered using the table resource?
var table = dynamoDbEnhancedClient.table("TableName", TableSchema.fromClass(PricingRule.class));
List<PricingRule> items = table.query(<condition>).items().stream().toList();
This code requires that PricingRule is defined as a dynamo bean, for example
#DynamoDbBean
public class PricingRule {
private String pk;
private String sk;
private String field1;
private String field2;
public PricingRule() {
}
#DynamoDbPartitionKey
public String getPk() {
return pk;
}
public void setPk(String pk) {
this.pk = pk;
}
#DynamoDbSortKey
public String getSk() {
return sk;
}
public void setSk(String sk) {
this.sk = sk;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
}
I got solution and posting if someone may come up with this problem in future.
public List<PricingRule> statementToList() {
List<PricingRule> pricingRules = new ArrayList<>();
try {
// Create ExecuteStatementRequest
ExecuteStatementRequest executeStatementRequest = createExecuteStatementRequest();
ExecuteStatementResult executeStatementResult = dynamoDB.executeStatement(executeStatementRequest);
final ObjectMapper mapper = new ObjectMapper();
executeStatementResult.getItems().forEach(item -> pricingRules.add(mapper.convertValue(ItemUtils.toSimpleMapValue(item), PricingRule.class)));
} catch (Exception e) {
handleExecuteStatementErrors(e);
}
return pricingRules;
}
I have a map in java which has String as Key and an integer list as value. My query returns the below set
"Day:1, Day:2, Day:3, Month:1, Year:15, Year:20, Year:25"
Meaning, I have keys and different values for each keys in random.. I am expecting an output of a map which has unique key and corresponding list of int in values as seen below:
{
"day": [1,2,3],
"Month": [1],
"year": [15,20,25]
}
Kindly help
public static void main(String[] args){
String input = "Day:1, Day:2, Day:3, Month:1, Year:15, Year:20, Year:25";
List<String> list = Arrays.asList(input.split(","));
JSONObject jsonObject = new JSONObject();
for (String val : list) {
String[] splitedValues = val.split(":");
if(jsonObject.has(splitedValues[0].trim())) {
jsonObject.getJSONArray(splitedValues[0].trim()).put(Integer.valueOf(splitedValues[1]));
}else {
List<Integer> integers = new ArrayList<Integer>();
integers.add(Integer.valueOf(splitedValues[1]));
jsonObject.put(splitedValues[0].trim(), integers);
}
}
System.out.println(jsonObject);
}
output
{"Month":[1],"Year":[15,20,25],"Day":[1,2,3]}
Please find below code. I have created an inner class to map type and value and then collected it by grouping the type.
import java.util.Map;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
public class StringToMap {
public static void main(String[] args) {
String queryOutput = "Day:1, Day:2, Day:3, Month:1, Year:15, Year:20, Year:25";
System.out.println(groupByTypeAndAddValuesToList(queryOutput));
}
private static Map<String, List<Integer>> groupByTypeAndAddValuesToList(String queryOutput) {
final String[] split = queryOutput.split(",");
return Arrays.stream(split).map(s -> {
final String trimmed = s.trim();
final String[] splitByColon = trimmed.split(":");
return new TypeValues(splitByColon[0], Integer.parseInt(splitByColon[1]));
}).collect(groupingBy(TypeValues::getType, Collectors.mapping(TypeValues::getValue, toList())));
}
private static class TypeValues {
private final String type;
private final Integer value;
public TypeValues(String type, Integer value) {
this.type = type;
this.value = value;
}
public String getType() {
return type;
}
public Integer getValue() {
return value;
}
}
}
I've defined the following set of data
Response response = new Response();
List<ObjectTest> objList = new ArrayList<ObjectTest>();
objList.add(new ObjectTest(new Attributes(new FirstName("ab","1"),new LastName("hernandez","2"))));
objList.add(new ObjectTest(new Attributes(new FirstName("jose","1"),new LastName("perez","2"))));
objList.add(new ObjectTest(new Attributes(new FirstName("paco","2"),new LastName("jackson","2"))));
objList.add(new ObjectTest(new Attributes(new FirstName("pedro","1"),new LastName("herrera","2"))));
objList.add(new ObjectTest(new Attributes(new FirstName("juan","2"),new LastName("flores","2"))));
response.setObjectList(objList);
So based on what the user selects I need to be able to get the specific class and the attribute, for example:
if the user selects [Attributes - FirstName - value] the output would be :
ab
jose
paco
pedro
juan
if the user selects [Attributes - LastName- status] the output would be:
2
2
2
2
2
The problem here is that I dont know how to get the specific class in runtime. Also the main object could have any number of classes inside of it like MainClass.ClassA.ClasstB.ClassX.classAttributeValue. The only thing that I know is that the last value is going to be the one that I have to take in that case I have to print classAttributeValue . Any ideas how to solve this using java 8 ?
Assuming your class structure looks something like this:
public static abstract class Attribute {
public final String value;
public final String status;
public Attribute(String value, String status) {
this.value = value;
this.status = status;
}
}
public static class FirstName extends Attribute {
public FirstName(String value, String status) {
super(value, status);
}
}
public static class LastName extends Attribute {
public LastName(String value, String status) {
super(value, status);
}
}
public static class Attributes {
public final FirstName firstName;
public final LastName lastName;
public Attributes(FirstName firstName, LastName lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
public static class ObjectTest {
public final Attributes attributes;
public ObjectTest(Attributes attributes) {
this.attributes = attributes;
}
}
You can define java.util.function.Function accessors for each stage:
Function<ObjectTest, Attributes> attributes = t -> t.attributes;
Function<Attributes, FirstName> firstName = t -> t.firstName;
Function<Attributes, LastName> lastName = t -> t.lastName;
Function<Attribute, String> value = t -> t.value;
Function<Attribute, String> status = t -> t.status;
And combine them like so:
Function<ObjectTest, String> attributeFirstNameValue =
attributes.andThen(firstName).andThen(value);
Function<ObjectTest, String> attributeLastNameStatus =
attributes.andThen(lastName).andThen(status);
Then apply the combined accessor to the list:
objList.stream().map(attributeFirstNameValue).forEach(System.out::println);
objList.stream().map(attributeLastNameStatus).forEach(System.out::println);
Is it critical to use this class structure?
In your example using a associative container is more suitable.
For example you can create class with structure like this:
Firstly you shoud something for itterate by Tree:
class DynamicObjectNode {
private HashMap<String, DynamicObjectNode> childs = new HashMap<>();
public HashMap<String, DynamicObjectNode> getChilds() {
return childs;
}
}
All values should be in leafs:
class DynamicObjectNodeValue<T> extends DynamicObjectNode {
public DynamicObjectNodeValue(T value) {
this.value = value;
}
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
#Override
public HashMap<String, DynamicObjectNode> getChilds() {
return null; //Tree leafs should not has childs
}
}
If you need to work with this as objects. You can use wrapped class like this:
class FirstNameAttribute extends DynamicObjectNode{
private static final String NameValueProperty = "NameValue";
private static final String StatusProperty = "Status";
private DynamicObjectNodeValue<String> nameValue = new DynamicObjectNodeValue<String>("Default name");
private DynamicObjectNodeValue<Integer> status = new DynamicObjectNodeValue<Integer>(1);
public FirstNameAttribute() {
getChilds().put(NameValueProperty, nameValue);
getChilds().put(StatusProperty, status);
}
public String getName() {
return nameValue.getValue();
}
public Integer getStatus() {
return status.getValue();
}
public void setName(String val) {
nameValue.setValue(val);
}
public void setStatus(Integer val) {
status.setValue(val);
}
}
So, with this code you can iterate it as a Tree and get values Dynamic.
And you can use this as objects to call some methods.
Thank you for your responses, what I finally did was to use JsonNode and based on the attribute I wanted to get I was iterating the same object and assign the result to se same object for example:
Json Response:
Object.Person1.firstName.value
I created an array of that and split it by "." then I created a for and I used this
jsonNode = jsonNode.get(inputArray[x]);
at the end the last element of the array is the one that I need so I added some logic to get it.
I have the following model classes:
package com.ab.model;
import java.util.List;
public class Request {
public Request(String requestType, Body body, List<String> emails) {
this.requestType = requestType;
this.body =body;
this.emails = emails;
}
private String requestType;
private Body body;
private List<String> emails;
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
public List<String> getEmails() {
return emails;
}
public void setEmails(List<String> emails) {
this.emails = emails;
}
}
class Body {
private String content;
private List<Header> headers;
public Body(String content, List<Header> headers) {
this.content = content;
this.headers = headers;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public List<Header> getHeaders() {
return headers;
}
public void setHeaders(List<Header> headers) {
this.headers = headers;
}
}
class Header {
private String headerName;
public Header (String headerName) {
this.headerName = headerName;
}
public String getHeaderName() {
return headerName;
}
public void setHeaderName(String headerName) {
this.headerName = headerName;
}
}
And the following instance of the Request class:
Request request = new Request(
"get",
new Body("abcdefg",
Arrays.asList(new Header("header_one"))),
Arrays.asList("a#a.com", "b#b.com"));
Do you know any library or algorithm that can serialize the request object into the following string?
requestType = "get"
body.content = "abcdefg"
body.headers[0].headerName = "header_one"
emails[0] = "a#a.com"
emails[1] = "b#b.com"
I know I can serialize it as json, xml, etc, but these don't fit my use case.
Basically I need a serialization like:
field.nestedField.reallyNestedField = "its primitive value"
As a next step, I am planning to read the generated string and generate arbitrary data for each field/nestedField then deserialize it back using PropertyUtils from Apache e.g.:
PropertyUtils.setProperty(requestObject, "requestType", "random type");
PropertyUtils.setProperty(requestObject, "body.content", "random content");
//...
Many thanks!
Andrei
What about overriding your toString() default methods to read and output your member variables as text. You can use super to refer to your SuperClass and it's members.
PS: You don't have default constructors in your classes! In case you have constructors with your argument list it is suggested to include your no-argument default constructor in your class! Especially in case you are implementing some logic related to serialisation / deserialisation!
You can iterate and recurse on the class/object properties using Commons PropertyUtils.
Depending on how complex your implementation is, you might need to do some type checking for primitive/wrapper/collection types (the below leverages Commons ClassUtils).
public static List<String> getPropertyDescriptorPaths(Class<?> clazz) {
return getPropertyDescriptorPaths("", clazz);
}
private static List<String> getPropertyDescriptorPaths(String prefix, Class<?> clazz) {
List<String> paths = new ArrayList<>();
PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(clazz);
for (PropertyDescriptor pd : descriptors) {
if (isSimpleType(pd.getPropertyType())) {
paths.add(prefix + pd.getName());
} else if (!pd.getName().equals("class")) {
paths.addAll(getPropertyDescriptorPaths(pd.getName() + ".", pd.getPropertyType()));
}
}
return paths;
}
private static boolean isSimpleType(Class<?> clazz) {
return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.equals(String.class) || isCollectionOrArray(clazz);
}
private static boolean isCollectionOrArray(Class<?> clazz) {
return isCollection(clazz) || clazz.isArray();
}
private static final List<Class<?>> COLLECTION_TYPES = Arrays.asList(new Class<?>[] { List.class, Map.class, Set.class });
private static boolean isCollection(Class<?> clazz) {
for (Class<?> eachClass : COLLECTION_TYPES) {
if (eachClass.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
The condition for comparing property name to class is because each object has a getClass() method, and we don't care about that.
Using this with your classes, we get the result:
System.out.println(getPropertyDescriptorPaths(Request.class));
// [emails, requestType, body.headers, body.content]
I've run into some funky behavior with generics and I was wondering if someone could shed some light as to why this is happening. To start, I have a class Foo which has a field id. The hashCode method on Foo just returns the id. In another class I create a Map<Foo, Double> bar = new HashMap<Foo, Double().
Then, at a later part of the code the strangeness starts, and I am able to do the following (simplified here):
Long baz = new Long(1);
bar.get(baz);
So, my question is, Why doesn't the compiler and catch this and report it as an error?
EDIT: I made one mistake in my initial question in that get is the method that works, not put. I have posted the full code below.
Map<WebPage, Double> scoresForPhrase = new HashMap<WebPage, Double>();
// Now that we have a list of matching docs, we can calculate the
// Score of each word in the phrase for each document
for (String term: phrase.getWords()) {
TreeSet<Posting> wordPostings = wordMap.get(term);
for(Long doc: matchingDocs) {
if (docDenomScores.get(doc) == null) {
docDenomScores.put(doc, getDocTotal(doc));
}
// The set is of postings, which are compared by docId, so
// we need a temporary one to enable searching
Posting temp = new Posting(doc, new ArrayList<Integer>());
Posting wordPosting = wordPostings.ceiling(temp);
WebPage page = (WebPage) mWebpageDb
.getPageIdToWebPageTable().get(doc);
score = getTermScore(wordPosting, page,
wordPostings.size());
score = score * queryTermWeights.get(term);
Double curScore = scoresForPhrase.get(doc);
}
}
As for the Foo class, it is:
public class WebPage implements Serializable {
private static final long serialVersionUID = -4907557806357281837L;
private String mUrl;
private int mMaxTf;
private long mPageId;
private long mLastTimeUpdated;
private List<Long> mParentIds;
private long mContentLength;
private String mTitle;
private List<Long> mChildren;
private List<String> mAllUrls;
public WebPage(String url, long pageId, long lastTimeUpdated,
List<Long> parentIds, long contentLength, String title, List<Long> children,
List<String> allUrls) {
super();
this.mUrl = url;
this.mPageId = pageId;
this.mLastTimeUpdated = lastTimeUpdated;
this.mParentIds = parentIds;
this.mContentLength = contentLength;
this.mTitle = title;
this.mChildren = children;
this.mAllUrls = allUrls;
this.mMaxTf = 0;
}
public void setUrl(String mUrl) {
this.mUrl = mUrl;
}
public void setPageId(int mPageId) {
this.mPageId = mPageId;
}
public void setLastTimeUpdated(long mLastTimeUpdated) {
this.mLastTimeUpdated = mLastTimeUpdated;
}
public void setParentIds(List<Long> mParentId) {
this.mParentIds = mParentId;
}
public void setContentLength(long mContentLength) {
this.mContentLength = mContentLength;
}
public void setChildren(List<Long> mChildren) {
this.mChildren = mChildren;
}
public void setAllUrls(List<String> allUrls) {
this.mAllUrls = allUrls;
}
public void setMaxTf(int newTf) {
this.mMaxTf = newTf;
}
public String getUrl() {
return mUrl;
}
public long getPageId() {
return mPageId;
}
public long getLastTimeUpdated() {
return mLastTimeUpdated;
}
public List<Long> getParentIds() {
return mParentIds;
}
public long getContentLength() {
return mContentLength;
}
public List<Long> getChildren() {
return mChildren;
}
public String getTitle() {
return mTitle;
}
public List<String> getAllUrls() {
return mAllUrls;
}
public int getMaxTf() {
return mMaxTf;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof WebPage)) {
return false;
} else {
return ((WebPage)o).mPageId == mPageId;
}
}
#Override
public int hashCode() {
return (int)mPageId;
}
public String toString() {
return mUrl;
}
}
So two things. First, remember that due to type-erasure there is no runtime checking of generic types. The Map<Foo, Double> simply becomes Map<Object, Object>.
Second, with regards to a compiler warning or error, you should get a warning or error if bar is declared of type Map<Foo, Double>. But if it is declared as Map, no warning or error. My guess is that bar is defined as Map bar.
UPDATE
The reason there is no error on get is that by definition get takes an Object not the generic type. It is one of the odd things about the interface.
Map.get
Your Map<Foo, Double> might have been casted to Map:
Map<Foo, Double> barOriginal = new HashMap<Foo, Double();
// ...
Map bar = barOriginal;
// ...
Long baz = new Long(1);
bar.put(baz, new Double(1));