I have a scenario to get a child hierarchy structure of a field till parent for doing field level validations.
Can someone provide some solution.
Pojo classes
Student.java
package com.poc.next.validations;
import java.util.ArrayList;
import java.util.List;
public class Student {
private String studentName;
private List<Subject> subjects;
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public List<Subject> getSubjects() {
if (subjects == null) {
return new ArrayList<>();
}
return subjects;
}
public void setSubjects(List<Subject> subjects) {
this.subjects = subjects;
}
}
Subject.java
package com.poc.next.validations;
import java.util.ArrayList;
import java.util.List;
public class Subject {
private String subjectName;
private List<RevisionMarks> revisionMarks;
public String getSubjectName() {
return subjectName;
}
public void setSubjectName(String subjectName) {
this.subjectName = subjectName;
}
public List<RevisionMarks> getRevisionMarks() {
if (revisionMarks == null) {
return new ArrayList<>();
}
return revisionMarks;
}
public void setRevisionMarks(List<RevisionMarks> revisionMarks) {
this.revisionMarks = revisionMarks;
}
}
RevisionMarks.java
package com.poc.next.validations;
public class RevisionMarks {
private Integer mark;
private String revision;
public Integer getMark() {
return mark;
}
public void setMark(Integer mark) {
this.mark = mark;
}
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
}
Now we are adding a validation to check whether the given mark in RevisionMarks class in valid or not. if it is equal to zero I have to add it to error dto and send it back to UI. The challenge here is i have to provide the field name dynamic in hierarchy like "subjects[0].revisionMarks[0].mark".
Main class
RevisionValidation.java
package com.poc.next.validations;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class RevisionValidation {
public static void main(String[] args) {
Student student = populateStudentData();
Iterator<Subject> iterator = student.getSubjects().iterator();
while (iterator.hasNext()) {
Subject subject = (Subject) iterator.next();
RevisionMarks revisionMarks = subject.getRevisionMarks().get(0);
System.out.println(revisionMarks.getMark());
if (revisionMarks.getMark() == 0) {
ErrorDTO errorDTO = new ErrorDTO(true, "Invalid Marks", "Error", "subjects[0].revisionMarks[0].mark",
"invalid_mark");
System.out.println(errorDTO);
}
}
}
private static Student populateStudentData() {
List<RevisionMarks> revisionMarks = new ArrayList<>();
RevisionMarks revisionMark = new RevisionMarks();
revisionMark.setMark(0);
revisionMark.setRevision("Test 1");
revisionMarks.add(revisionMark);
List<Subject> subjects = new ArrayList<>();
Subject subject = new Subject();
subject.setSubjectName("CS");
subject.setRevisionMarks(revisionMarks);
subjects.add(subject);
Student student = new Student();
student.setStudentName("Sample");
student.setSubjects(subjects);
return student;
}
}
How can I dynamically create the fieldpath like "subjects[0].revisionMarks[0].mark".
Any suggestions are welcome. Thanks in advance.
Use a counter:
int counter = 0;
Iterator<Subject> iterator = student.getSubjects().iterator();
while (iterator.hasNext()) {
Subject subject = (Subject) iterator.next();
RevisionMarks revisionMarks = subject.getRevisionMarks().get(0);
System.out.println(revisionMarks.getMark());
if (revisionMarks.getMark() == 0) {
ErrorDTO errorDTO = new ErrorDTO(true, "Invalid Marks", "Error", "subjects[" + counter + "].revisionMarks[0].mark",
"invalid_mark");
System.out.println(errorDTO);
}
++counter;
}
I would suggest to use JSR3 validation instead of reinventing wheel.
https://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
You can add necessary annotations for each field in your POJO and add #Valid annotation to let validator check nested POJO objects.
The link
https://www.beyondjava.net/blog/how-to-invoke-jsr-303-bean-validation-programmatically/ shows how to call the validator programmatically.
With the validation you can provide any messages and localize them, and the xpaths are built automatically pointing problems in POJO or nested POJOs.
Related
I'm having a problem with an arrayList in which I store member objects. I think it might be something to do with the way i've declared it. This is what I have so far
Member Class
package assignment;
import java.util.ArrayList;
public class Member {
private int memberID;
private String memberName;
private int memberAge;
private int numOfBooksLoaned;
private int penalties;
public Member(int memberID, String memberName, int memberAge, int numOfBooksLoaned, int penalties) {
this.memberID = memberID;
this.memberName = memberName;
this.memberAge = memberAge;
this.numOfBooksLoaned = numOfBooksLoaned;
this.penalties = penalties;
}
public int getMemberID() {
return memberID;
}
public void setMemberID(int memberID) {
this.memberID = memberID;
}
public String getMemberName() {
return memberName;
}
public void setMemberName(String memberName) {
this.memberName = memberName;
}
public int getMemberAge() {
return memberAge;
}
public void setMemberAge(int memberAge) {
this.memberAge = memberAge;
}
public int getNumOfBooksLoaned() {
return numOfBooksLoaned;
}
public void setNumOfBooksLoaned(int numOfBooksLoaned) {
this.numOfBooksLoaned = numOfBooksLoaned;
}
public int getPenalties() {
return penalties;
}
public void setPenalties(int penalties) {
this.penalties = penalties;
}
}
MemberList class
package assignment;
import java.util.Scanner;
import java.util.ArrayList;
public class MemberList {
private ArrayList<Member> Members;
public MemberList(ArrayList<Member> Members)
{
this.Members = Members;
}
public void addNewMember()
{
Scanner input = new Scanner(System.in);
boolean successful = false;
int memberID;
String memberName;
int memberAge;
do {
System.out.println("/t/tCreate new member" + "/nPlease enter your full name: ");
memberName = input.nextLine();
for (int i = 0; i < Members.size(); i++) {
if (Members.get(i).getMemberName().equalsIgnoreCase(memberName)) {
System.out.println("This member name is already in use");
} else {
successful = true;
}
}
} while (successful == false);
The problem is just after the for loop in the if statement
if (Members.get(i).getMemberName().equalsIgnoreCase(memberName))
the error says that getMemberName() is undefined for type Member.
Any ideas?
I have used this exact same identical way of using an arrayList and it works fine but it isn't working now for some reason.
try to use a foreach loop in this way
for (Member m : Members) {
if (m.getMemberName().equalsIgnoreCase(memberName)) {
System.out.println("This member name is already in use");
} else {
successful = true;
}
}
Another thing, is discouraged to use Capital letter at first letter in class members in Java, define the list as
private ArrayList<Member> members;
I tried to create ArrayList with Ingredients object and then iterate through this list but this is only showing the last added ingredient. For example when I'm adding two ingredients (mushrooms, tomatoes) in arrayList are only tomatoes with index 0 and 1.
import java.util.ArrayList;
import java.util.List;
public class Ingredients {
private String ingredientName;
private int ingriedientQuantity;
List<Ingredients> ingredients;
public Ingredients() {
this.ingredients = new ArrayList<>();
}
public void addIngredient(Ingredients ingredient) {
ingredients.add(ingredient);
}
public String getIngredientName() {
return ingredientName;
}
public void setIngredientName(String ingredientName) {
this.ingredientName = ingredientName;
}
public int getIngriedientQuantity() {
return ingriedientQuantity;
}
public void setIngriedientQuantity(int ingriedientQuantity) {
this.ingriedientQuantity = ingriedientQuantity;
}
public void showIngredients() {
for (Ingredients ingredientI : ingredients) {
System.out.println(ingredientI.getIngredientName() + " " + ingredientI.getIngriedientQuantity());
}
}
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Ingredients ing = null;
boolean exitFlag = false;
String name;
int quantity;
int option = 0;
String o;
while (!exitFlag) {
System.out.println("1 - Add");
System.out.println("2 - Show");
System.out.println("3 - Exit");
option = sc.nextInt();
sc.nextLine();
switch (option) {
case 1:
ing = new Ingredients();
do {
System.out.println("Product name: ");
name = sc.nextLine();
ing.setIngredientName(name);
System.out.println("Quantity");
quantity = sc.nextInt();
sc.nextLine();
ing.setIngriedientQuantity(quantity);
System.out.println("Add more? Y/N");
o = sc.nextLine();
ing.addIngredient(ing);
} while (!o.equalsIgnoreCase("N"));
break;
case 2:
ing.showIngredients();
break;
case 3:
exitFlag = true;
break;
default:
System.out.println("Error");
break;
}
}
sc.close();
}
}
Is better way to do it?
Your class design is wrong. Create a separate class Ingredient with properties IngredientName and IngredientQuantity. The Ingredients class maintains an ArrayList for Ingredient objects.
A sample Ingredient class may look like:
import java.util.ArrayList;
import java.util.List;
public class Ingredient {
private String ingredientName;
private int ingriedientQuantity;
public Ingredient() {
}
public String getIngredientName() {
return ingredientName;
}
public void setIngredientName(String ingredientName) {
this.ingredientName = ingredientName;
}
public int getIngriedientQuantity() {
return ingriedientQuantity;
}
public void setIngriedientQuantity(int ingriedientQuantity) {
this.ingriedientQuantity = ingriedientQuantity;
}
}
Your Ingredients can be implemented as:
import java.util.ArrayList;
import java.util.List;
public class Ingredients {
List<Ingredient> ingredients;
public Ingredients() {
this.ingredients = new ArrayList<Ingredient>();
}
public void addIngredient(Ingredient ingredient) {
ingredients.add(ingredient);
}
public void showIngredients() {
for (Ingredient ingredientI : ingredients) {
System.out.println(ingredientI.getIngredientName() + " " + ingredientI.getIngriedientQuantity());
}
}
}
I would personnaly create a "Recipe" Class as follow :
public class Recipe {
private List<Ingredients> ingredients;
+ getters and setters
}
Then change a little bit your ingredient class :
public class Ingredient {
private String ingredientName;
private int ingredientQuantity;
...
}
Then in your main method create a Recipe at the beginning, and then in your while loop create a new instance of Ingredient each time and add it to your recipe.
Is it a good idea to write example data within a class which can be instantiated?
In the following example, i am using some static var's which are used to get direct access to some Contacts via:
Contact.contact101()
...
I am using this example data definition within a test and don't want to write a kind of util class which contains all the example data.
package com.example.webdriver.util.builder.model;
import com.google.gson.annotations.SerializedName;
import com.example.webdriver.util.builder.LocalStorageBuilder;
import com.example.webdriver.util.builder.enumaration.UserStatus;
public class Contact {
#SerializedName("ID")
private Long id;
#SerializedName("puid")
private Long principleUserId;
#SerializedName("cuid")
private Long contactUserId;
#SerializedName("v")
private int visible;
#SerializedName("ustat")
private String userStatus;
#SerializedName("ats")
private Long addedTimeStamp;
private static Contact contact101;
private static Contact contact102;
private static Contact contact305;
private static Contact contact302;
private static Contact contact301;
private static Contact contact382;
public Contact() {
this.id = LocalStorageBuilder.getContactIdCounter();
this.principleUserId = LocalStorageBuilder.principalUserId;
this.contactUserId = 301L;
this.visible = 1;
this.userStatus = String.valueOf(UserStatus.ONLINE.getUserStatus());
this.addedTimeStamp = 1410168552386L;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPrincipleUserId() {
return principleUserId;
}
public void setPrincipleUserId(Long principleUserId) {
this.principleUserId = principleUserId;
}
public int getVisible() {
return visible;
}
public void setVisible(boolean visible) {
if (visible) {
this.visible = 1;
} else {
this.visible = 0;
}
}
public String getUserStatus() {
return userStatus;
}
public void setUserStatus(UserStatus userStatus) {
this.userStatus = String.valueOf(userStatus.getUserStatus());
}
public Long getAddedTimeStamp() {
return addedTimeStamp;
}
public void setAddedTimeStamp(Long addedTimeStamp) {
this.addedTimeStamp = addedTimeStamp;
}
public Long getContactUserId() {
return contactUserId;
}
public void setContactUserId(Long contactUserId) {
this.contactUserId = contactUserId;
}
// Example data
public static Contact contact102() {
if (contact102 == null) {
contact102 = createContact(102L);
}
contact102.setPrincipleUserId(LocalStorageBuilder.principalUserId);
return contact102;
}
public static Contact contact302() {
if (contact302 == null) {
contact302 = createContact(302L);
}
contact302.setPrincipleUserId(LocalStorageBuilder.principalUserId);
return contact302;
}
public static Contact contact305() {
if (contact305 == null) {
contact305 = createContact(305L);
}
contact305.setPrincipleUserId(LocalStorageBuilder.principalUserId);
return contactAVG305;
}
private static Contact createContact(Long contactUserId) {
Contact contact = new Contact();
contact.setContactUserId(contactUserId);
contact.setPrincipleUserId(LocalStorageBuilder.principalUserId);
contact.setUserStatus(UserStatus.ONLINE);
contact.setAddedTimeStamp(1410168552386L);
contact.setVisible(true);
return contact;
}
}
No, use some kind of factory instead.
There are various terms around the internet, ObjectMother is one, although I prefer TestDataFactory.
public class TestDataFactory {
private static Contact createContact(Long contactUserId) {
Contact contact = new Contact();
contact.setContactUserId(contactUserId);
contact.setPrincipleUserId(LocalStorageBuilder.principalUserId);
contact.setUserStatus(UserStatus.ONLINE);
contact.setAddedTimeStamp(1410168552386L);
contact.setVisible(true);
return contact;
}
}
The advantage is that this can live in your test sources, not poluting your domain objects with test code.
This makes re factoring tough and as per class definition, this is not valid here.
The correct place is to create another class named TestDataHelper and create a method named getContacts and return list of Contact objects.
Concerns should always be separated. This is how Java works !
What I am doing is getting elements from a map and adding them onto a JList to display on a GUI. I want to know how to sort the names alphabetically.
private void refreshShopsList() {
gameShopsJList.setModel(new javax.swing.AbstractListModel<String>() {
public int getSize() {
return ShopsLoader.getShops().size();
}
public String getElementAt(int i) {
return getShopByIndex(i).getName();
}
});
}
private Shop getShopByIndex(int index) {
Iterator<Entry<String, Shop>> it = ShopsLoader.getShops().entrySet().iterator();
int count = -1;
while(it.hasNext()) {
Entry<String, Shop> entry = it.next();
count++;
if (count == index)
return entry.getValue();
}
return null;
}
/**
* The map of the shops
*/
private static final Map<String, Shop> shops = new HashMap<String, Shop>();
public static Map<String, Shop> getShops() {
return shops;
}
Here is a little example, which sorts your shop names.
The ShopComparator class does the sorting task:
package model;
import java.util.Comparator;
public class ShopComparator implements Comparator<Shop> {
#Override
public int compare(Shop o1, Shop o2) {
return o1.getName().compareTo(o2.getName());
}
}
The Shop class, as simple as possible:
package model;
public class Shop {
private int id;
private String name;
public Shop(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And the main app:
package model;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
public class App {
public static void main(String[] args) {
Map<String, Shop> shops = new HashMap<String, Shop>();
Shop s1 = new Shop(1, "Apus Drugstore");
Shop s2 = new Shop(2, "DM");
Shop s3 = new Shop(3, "Kaufhof");
Shop s4 = new Shop(4, "Moes Traverne");
shops.put("one", s3);
shops.put("two", s4);
shops.put("three", s1);
shops.put("four", s2);
for(Shop s : shops.values()) {
System.out.println(s.getName());
}
ShopComparator sc = new ShopComparator();
TreeSet<Shop> sortedShops = new TreeSet<>(sc);
sortedShops.addAll(shops.values());
for(Shop s : sortedShops) {
System.out.println(s.getName());
}
}
}
First output, unsorted:
Moes Traverne
Kaufhof
Apus Drugstore
DM
and the sorted output.
Apus Drugstore
DM
Kaufhof
Moes Traverne
Algorithm:
get all values from JList, convert them to strings, store in array
sort the array
set new values to JList.
code:
JList jl = new JList(new Object[]{4.5,1,"Hi!"});
ListModel model = jl.getModel();
String[] strings = new String[model.getSize()];
for(int i=0;i<strings.length;i++){
strings[i]=model.getElementAt(i).toString();
}
Arrays.sort(strings);
jl.setListData(strings);
see about Comparator if you need to sort array in any other order.
I have a custom java class which has an ArrayList and corresponding to it have a custom vo class which has ArrayCollection (in Flex).
I want to return data from Java to flex. Every variable in java is getting mapped to vo perfectly except for ArrayList.
When trying to retrive
When trying to retrive exposureUSDList (which is an arrayList) in flex I am getting empty ArrayCollection. It is not getting mapped properly
Please find my code below:
Flex Code:
package com.example.vo
{
import com.adobe.cairngorm.vo.IValueObject;
import mx.collections.ArrayCollection;
[Bindable]
[RemoteClass(alias="com.example.vo.Summary")]
public class Summary
{
public var productId : String;
public var clientId : String;
public var brokerId : String;
public var acctNo : Number;
public var exposureUSDList:ArrayCollection=new ArrayCollection();
}
}
Java code:
package com.example.vo;
import java.io.Serializable;
import java.util.ArrayList;
public class Summary implements Serializable {
static final long serialVersionUID = -1L;
private String productId ;
private String clientId ;
private String brokerId ;
private String acctNo ;
private ArrayList exposureUSDList= new ArrayList();
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getBrokerId() {
return brokerId;
}
public void setBrokerId(String brokerId) {
this.brokerId = brokerId;
}
public int getAcctNo() {
return acctNo;
}
public void setAcctNo(int acctNo) {
this.acctNo = acctNo;
public ArrayList getExposureUSDList() {
return exposureUSDList;
}
public void setExposureUSDList(double exposureUSD) {
this.exposureUSDList.add(exposureUSD);
}
}
Please Help!!
I think the reason could be that you're passing double to the array list setter. Try pass ArrayList.