Writing a code for checking data on different conditions.
I have an ArrayList of CRM objects "actionsList" (made in another class).
Here I check these objects for different conditions.
Objects which satisfy the conditions I have to add to the ArrayList "remarksList".
The question is how to create a method setRemarkObject() to set all data to remarkObject at once?
Not to write each time:
remarkObject.setRemark(checkString);
remarkObject.setNumber(crm.getNumber());
remarkObject.setDealer(crm.getDealer());
remarkObject.setName(crm.getName());
...
is it correct now?
import java.util.ArrayList;
public class Conditions {
static ArrayList<CRM> remarksList = new ArrayList<CRM>();
public ArrayList<CRM> conditionsChecking() {
for (CRM crm : App.actionsList) {
CRM remarkObject = new CRM();
remarkObject.setNumber(crm.getNumber());
remarkObject.setDealer(crm.getDealer());
remarkObject.setName(crm.getName());
remarkObject.setGroup(crm.getGroup());
remarkObject.setClientStatus(crm.getClientStatus());
remarkObject.setEntity(crm.getEntity());
remarkObject.setTypeOfContact(crm.getTypeOfContact());
remarkObject.setTypeOfFirstContact(crm.getTypeOfFirstContact());
remarkObject.setSourceOfFirstContact(crm
.getSourceOfFirstContact());
remarkObject.setOfferType(crm.getOfferType());
remarkObject.setEventDate(crm.getEventDate());
remarkObject.setBrand(crm.getBrand());
remarkObject.setCarClass(crm.getCarClass());
remarkObject.setModel(crm.getModel());
remarkObject.setCarCode(crm.getCarCode());
remarkObject.setWeek(crm.getWeek());
remarkObject.setMonth(crm.getMonth());
remarkObject.setYear(crm.getYear());
remarkObject.setAmmount(crm.getAmmount());
remarkObject.setSalesman(crm.getSalesman());
remarkObject.setPhone(crm.getPhone());
remarkObject.setEmail(crm.getEmail());
remarkObject.setAddress(crm.getAdress());
remarkObject.setCreationDate(crm.getCreationDate());
remarkObject.setCreationTime(crm.getCreationTime());
remarkObject.setModificationDate(crm.getModificationDate());
remarkObject.setModificationTime(crm.getModificationTime());
remarkObject.setBackdating(crm.getBackdating());
if ((crm.getClientStatus().equals("Yes")) && ((crm.getAdress().isEmpty()))){
crm.setRemark("Client's address is empty");
remarksList.add(remarkObject);
}
else if ((crm.getClientStatus().equals("Yes")) && (crm.getPhone().isEmpty())){
crm.setRemark( "Phone field is empty");
remarksList.add(remarkObject);
}
///....
else
crm.setRemark("Nothing wrong");
/// not adding to remarksLis
}
return remarksList;
}
}
You seem to be doing the same thing over and over again, with the addition of a String which states if a field is left empty. So Why not move the setters one block up, outside of the for loop?
static ArrayList<CRM> remarksList = new ArrayList<CRM>();
public ArrayList<CRM> conditionsChecking() {
for (CRM crm : App.actionsList) {
CRM remarkObject = new CRM();
remarkObject.setNumber(crm.getNumber());
remarkObject.setDealer(crm.getDealer());
remarkObject.setName(crm.getName());
remarkObject.setGroup(crm.getGroup());
//etcetera, etcetera, all setters, except remark
if ((crm.getClientStatus().equals("Yes")) && ((crm.getAdress().isEmpty())))
crm.setRemark("Client's address is empty");
else if ((crm.getClientStatus().equals("Yes")) && (crm.getPhone().isEmpty()))
crm.setRemark( "Phone field is empty");
// etc, etc
else
remarksList.add(remarkObject);
}
return remarksList;
}
For setters and getters in general, you can also use a constructor:
public CRM(String number, String dealer, String name, ...) {
this.number = number;
//...etc
}
Or a builder
public CRM() {}
public CRM setNumber(String number) {
this.number = number;
return this;
}
public CRM setDealer(String dealer) {
this.dealer = dealer;
return this;
}
//and use it like this
CRM crm = new CRM().setNumber("123").setDealer("dealer"); //et cetera
From what I understand you are copying the crm object into the remarkObject in every if-else statements. Why not copy it before all the if statements and only set the remark(checkString) inside the if-else statements? Then you can add it to remarkList after all of those statements.
You can copy the object using CRM constructor ie. CRM(CRM crm) or by cloning the object:
How do I copy an object in Java?
Also you are checking crm.getClientStatus().equals("Yes") in every of your if statement - why not check it once at a begining?
Related
I have two classes, one named Bird the other Runtime. The bird class creates birds - name, latin name. The Runtime class has 4 methods, only one is important for this question, that is the 'add' method. The add method when called upon needs to take input from the user that is name and latin name, these are saved into a string variable 'name' and 'latin name' and I call the Bird class constructor and pass in these string variables into its parameter and finally it is added to an ArrayList. However I get duplicate values, if I were to write the same bird twice.
I have tried to convert the ArrayList into a set and convert it back again into an ArrayList, i did this within the add method, this did not work. I suspect it is down to my poor understanding of how objects are stored in an ArrayList. I also created a getName method within the Bird class, so I can use list.get(i).getName, and if the name is equal to the one typed by the user, it prompts the user accordingly, if not it is added to my ArrayList. This also did not work. I also tried a for loop that would go through the ArrayList and an if statement would determine if the name typed by the user exists within the ArrayList, this also did not work, the attempt was early on so I can't remember exactly the error message, but the add method is called from within a while loop, and I think the error message was concurrent modification, I'm not entirely sure so please ignore that, my point is showing the various solutions I tried.
Below is The Bird class
public class Bird{
int obeservation = 0;
String name;
String latinName;
public Bird(String name, String latinName){
this.name = name;
this.latinName = latinName;
}
public void addBird(String name, String latinName){
this.name = name;
this.latinName = latinName;
}
public String getName(){
return this.name;
}
public String statistics(){
return this.name + " (" + this.latinName + ") : " +
this.obeservation + " observation";
}
}
Below is the Runtime class
public class Runtime {
ArrayList<Bird> birds = new ArrayList<Bird>();
Scanner scan = new Scanner(System.in);
public void scan() {
System.out.println("?");
String answer = scan.nextLine().trim();
while (!answer.equalsIgnoreCase("EXIT")) {
System.out.println("?");
answer = scan.nextLine().trim().toUpperCase();
if (answer.equalsIgnoreCase("ADD")) {
add();
} else if (answer.equalsIgnoreCase("OBSERVATION")) {
observation();
} else if (answer.equalsIgnoreCase("STATISTICS")) {
System.out.println("jhjh");//just to see if this is
working
statistics();
}
}
}
below is the add method, also what I've commented is the attempts,
currently the add method does not have an if statements to decide duplicates.
public void add() {
System.out.print("Name: ");
String name1 = scan.nextLine().trim().toUpperCase();
System.out.print("Latin Name: ");
String latinName1 = scan.nextLine().trim().toUpperCase();
birds.add(new Bird(name1, latinName1));
/*
Bird newBird = new Bird(name1, latinName1);
for (int i = 0; i < birds.size(); i++) {
if (birds.get(i).getName().equals(name)) {
System.out.println("Bird already exist");
return;
} else {
birds.add(newBird);
}
}
/*
* hBirds.addAll(birds); birds = new ArrayList<Bird>();
birds.addAll(hBirds);
*
* // Bird newBird = new Bird(name, latinName);
* /* if(birds.contains(name)){
* System.out.println("That name already exist");
* return;
* }else{
* birds.add(newBird(name, latinName));
*
* }
*/
}
The statistics method prints out the ArrayList, a foreach loop that goes through the ArrayList prints it out. The expected result if I input seagull twice should be one seagull value not two. How do i reject the duplicate?
You can have two approaches here:
First: Traverse through ArrayList, if you can't find the same bird, add it to ArrayList. It is a worse approach.
Second: Store birds inside HashSet. In this case, you need to override .hashCode() and .equals(Object obj) methods. It is a better approach.
Before talking about how to generate .hashCode() and .equals(Object obj) methods, I want to mention about .hashCode() method and HashSet<T>.
HashSet<T>s provide a unique set of the elements inside. To achieve this, .hashCode() method of a class is used. If you override .hashCode() method in any class, you can get the benefit of using HashSet<T>s. If you don't override this method, Java automatically returns the memory address of the object. That's why your HashSet<Bird> was including duplicate elements.
.hashCode() and .equals() methods can be generated by lots of IDEs. I copied and pasted your Bird class to Eclipse. By using Alt+Shift+S -> h for Eclipse or Alt+Insert -> equals() and hashCode() for IntelliJ, automatically generated the methods below:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((latinName == null) ? 0 : latinName.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + obeservation;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Bird other = (Bird) obj;
if (latinName == null) {
if (other.latinName != null)
return false;
} else if (!latinName.equals(other.latinName))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (obeservation != other.obeservation)
return false;
return true;
}
If you add these methods(I encourage you to generate in your IDE) to Bird class, you can use HashSet<Bird>. To avoid duplicates, simply add all of your Bird objects into defined HashSet<Bird>. You don't need any other data structure or equality check to control if any two Bird type objects are equal.
You will just need to change your object collection from ArrayList<Bird> birds = new ArrayList<Bird>(); to Set<Bird> birds = new HashSet<>();.
Move the add out of the loop:
for (int i = 0; i < birds.size(); i++) {
if (birds.get(i).getName().equals(name1)) {
System.out.println("Bird already exist");
return;
}
}
birds.add(new Bird(name1, latinName1));
In the interest of not creating more variables than necessary and cluttering up within the scope of a method that could otherwise have been very slim, I've, instead, created a temporary to hold all of the files I'm going to be referencing throughout the rest of the method.
I dislike this solution because it creates an array object every time it is run when an array object is not necessary to be created.
I could also not use the array or wall of variables, and instead reference the get methods directly, but that creates a lot of redundancy as I am performing the same methods repeatedly, and I dislike that even more.
public void savePrices() {
MFilePrices file[] = {AutoEcon.files().getPrices(), AutoEcon.files().getIntangibles(), AutoEcon.files().getGroups()};
for (String price : sellPrices.keySet()) {
if (EconItem.fromString(price) != null) {
file[0].setPrice(price, sellPrices.get(price).getExpression());
file[0].setBuyRate(price, sellPrices.get(price).getBuyRate());
} else if (file[1].getLabels().contains(price)) {
file[1].setPrice(price, sellPrices.get(price).getExpression());
file[1].setBuyRate(price, sellPrices.get(price).getBuyRate());
} else if (file[2].getLabels().contains(price)) {
file[2].setPrice(price, sellPrices.get(price).getExpression());
file[2].setBuyRate(price, sellPrices.get(price).getBuyRate());
}
}
}
public Double setExpression(String id, String expr) {
savePrices();
MFilePrices file[] = {AutoEcon.files().getPrices(), AutoEcon.files().getIntangibles(), AutoEcon.files().getGroups()};
if (EconItem.fromString(id) != null)
file[0].setPrice(id, expr);
else if (file[1].getLabels().contains(id))
file[1].setPrice(id, expr);
else if (file[2].getLabels().contains(id))
file[2].setPrice(id, expr);
else return null;
sellPrices.clear();
total=0;
loadPrices(AutoEcon.plugin());
return sellPrices.get(id).getPrice();
}
Another solution could be to create an array within the FilePool class where I'm getting the files from, which contains those three configuration files, or a method which puts them into an array and sends over the array. However, the latter just moves the problem over to another class, and the former is still creating a single array that is not totally necessary.
Both of these solutions just moves the problem from one class to another.
public class FilePool {
private Config config;
private Prices prices;
private Intangibles i;
private Groups groups;
private Logs econLogs;
private ItemAliases a;
public FilePool(AutoEcon pl) {
config = new Config(pl);
prices = new Prices(pl);
i = new Intangibles(pl);
econLogs = new Logs(pl);
a = new ItemAliases(pl);
new ReadMe(pl);
}
public Config getConfig() {
return config;
}
public Prices getPrices() {
return prices;
}
public Groups getGroups() {
return groups;
}
public Intangibles getIntangibles() {
return i;
}
public Logs getLogs() {
return econLogs;
}
public ItemAliases getAliases() {
return a;
}
}
(Ignore the dumb variable names in the FilePool class, I just loved the fact that they all line up so perfectly. Will be naming appropriately before publishing)
I know I'm being a bit over-anal about this tiny thing that won't affect the running program at all, but after being constantly harassed for every minor detail of my code by my colleagues in the past, I've grown to be a bit of a perfectionist.
Thanks to anyone who spent their time reading this. <3
The creation of the array is not a problem. Resources to create an array are meaningless. What is more of a problem is that anyone reading your code will struggle to understand what the magic indices represent without referring back to the array. Which means that you should turn them into named constants which will complicate your code even further.
Much better is to have clear variable names that represent what each element represents. Also a good idea to iterate through the map so you can avoid getting the value for each item:
FilePool files = AutoEcon.files();
final MFilePrices prices = files.getPrices();
final MFilePrices intangibles = files.getIntangibles();
final MFilePrices groups = files.getGroups();
sellPrices.forEach((price, value) -> {
if (EconItem.fromString(price) != null) {
setPriceAndBuyRate(prices, price, value);
} else if (intangibles.getLabels().contains(price)) {
setPriceAndBuyRate(intangibles, price, value);
} else if (groups.getLabels().contains(price)) {
setPriceAndBuyRate(groups, price, value);
}
});
private void setPriceAndBuyRate(MFilePrices filePrices, Price price, Value value) {
filePrices.setPrice(price, value.getExpression());
filePrices.setBuyRate(price, value.getBuyRate());
}
If you're concerned that the number of variables make the method difficult to read then move the logic for comparing the price to the labels and setting the price and buy rate into a separate class. That's a good practice in any case as it gives the class a single reason to change.
I am busy with a project that extracts data from a xml file and displays it in a word document. I have created a method for this extraction, but I want to simplify it by using an array of methods.
This is just an example of how I test for certain information at the moment:
for (int i = 0; i < nodeMap.getLength(); i++) {
Node node = nodeMap.item(i);
if (node.getNodeName().equalsIgnoreCase("maximumRedeliveries")) {
if (node.getNodeValue().startsWith("{{")) {
retryLogic.setMaximumRedeliveries(extractPropertyName(node.getNodeValue(), propFileLocation));
} else {
retryLogic.setMaximumRedeliveries(node.getNodeValue());
}
}
if (node.getNodeName().equalsIgnoreCase("asyncDelayedRedelivery")) {
if (node.getNodeValue().startsWith("{{")) {
retryLogic.setAsyncDelayedRedelivery(extractPropertyName(node.getNodeValue(), propFileLocation));
} else {
retryLogic.setAsyncDelayedRedelivery(node.getNodeValue());
}
}
}
I am aiming to create an array for the if statement values, for example "maximumRedeliveries" and "asyncDelayedRedelivery" and an array for their corresponding methods, for example setMaximumRedeliveries(),setAsyncDelayedRedelivery(). I am unsure of how to create an array of methods, or if it's even possible?
This problem differs form Java - Creating an array of methods, because I use set methods and don't know how to implement it in that way.
First, ensure that extractPropertyName takes names with and without curly braces, and behaves like this:
String extractOptionalPropertyName(String name, String propFileLocation) {
return name..startsWith("{{") ? extractPropertyName(name, propFileLocation) : name;
}
This moves conditionals from your XML processing code into a helper:
String nodeName = node.getNodeName();
if (nodeName.equalsIgnoreCase("maximumRedeliveries")) {
retryLogic.setMaximumRedeliveries(extractOptionalPropertyName(node.getNodeValue(), propFileLocation));
} else if (nodeName.equalsIgnoreCase("asyncDelayedRedelivery")) {
retryLogic.setAsyncDelayedRedelivery(extractOptionalPropertyName(node.getNodeValue(), propFileLocation));
} ... // and so on
With these changes in place, you can follow the recipe from this other Q&A and make a Map<String,ValSetter> objects, like this:
interface ValSetter {
void set(RetryLogic logic, String val);
}
// The map can be made static in a class
Map<String,ValSetter> setterForName = new HashMap<>();
{ // Initializer block
setterForName.put("maximumredeliveries", new ValSetter() {public void set(RetryLogic logic, String val) { logic.setMaximumRedeliveries(val);}} );
setterForName.put("asyncrelayedredelivery", new ValSetter() {public void set(RetryLogic logic, String val) { logic.setAsyncDelayedRedelivery(val);}} );
}
Now your XML handler could look like this:
String nodeName = node.getNodeName();
ValSetter setter = setterForName.get(nodeName.toLowerCase());
if (setter != null) {
String val = extractOptionalPropertyName(node.getNodeValue(), propFileLocation);
setter.set(retryLogic, val);
} else {
// report an error
}
I have a product class
public class Produs {
private String denumire;
private String categorie;
private String taraOrigine;
private double pret;
}
with different constructors to fit my needs. I have an ArrayList of this type where all the Products have all the fields ( the list is generated by parsing a file ) . And another list in which there are products with only the name and country of origin filled ( rest of the fields are null ).This list is also generated from another list.
My question is , how can I search the first list, using the known fields of a product located in the second list , so that I can complete every object in the first list ?
I have tried with
public Produs getProdus(Produs p)
{
for(Produs prod:produse)
{
if ((prod.getDenumire().equals(p.getDenumire()) && (prod.getTaraOrigine().equals(p.getTaraOrigine()))));
{
return prod;
}
}
return null;
}
where produse is my list of products where all fields have values and p is a Product constructed using only 2 fields.
I have also tried with overwriting equals and hashcode. The problem is that when it finds the element , the loop stops.
You need to populate it before returning the actual object.
public Produs getProdus(Produs p)
{
for(Produs prod:produse)
{
if ((prod.getDenumire().equals(p.getDenumire()) && (prod.getTaraOrigine().equals(p.getTaraOrigine()))));
{
if (prod.getCategorie() == null) {
prod.setCategorie(p.getCategorie());//assuming you have getter and setter already in Produs
}
return prod;//remove this statement, if you want multiple products to be updated and make this method as void type instead of returning Produs type. Remove return null as well from end of this method.
}
}
return null;
}
If you want to list all the producs whose criteria matches then you could create a list and populate that like below:
public void getProdus(Produs p)
{
List<Produs> productList = new ArrayList<Produs>();
for(Produs prod:produse)
{
if ((prod.getDenumire().equals(p.getDenumire()) && (prod.getTaraOrigine().equals(p.getTaraOrigine()))));
{
productList.add(prod);
}
}
for(Produs prod:productList) {//iterate over the list who matched the criteria and amend it with properties from p.
}
}
Your getProdus() function is correct. You need to call it in a loop for every object in the first list.
My issue is related to design currently. I am having a jsf parameter page and it submits
different parameters to generate a jasper report. E.g. Nationality, Travel type, Visa type,
Gender and so on. Parameters can be a combination. E.g. At one time user can select
nationality and visatype and leave others blank which will make other's default to the value
of ALL. I submit the id's from the parameter page. If nothing was selected by the user i am
setting the values manually to ALL in the setter methods. Here is a snapshot of my managed
bean method and the POJO.
private ReportBean generateReportBean(TravelDetailSearchParams searchParams, String reportPath){
TravelDetailReportBean travelDetailReportBean = new TravelDetailReportBean();
if(searchParams.getGender().getId() != 0){
for(Lookup lookup : gender){
if(lookup.getId() == searchParams.getGender().getId()){
travelDetailReportBean.setGender(lookup.getDescEnglish());
break ;
}
}
}
else{
travelDetailReportBean.setGender(searchParams.getGender().getDescEnglish());
}
if(searchParams.getTravelType().getId() != 0){
for(Lookup lookup : travelType){
if(lookup.getId() == searchParams.getTravelType().getId()){
travelDetailReportBean.setTravelType(lookup.getDescEnglish());
break ;
}
}
}
else{
travelDetailReportBean.setTravelType(searchParams.getTravelType().getDescEnglish());
}
if(searchParams.getPort().getId() != 0){
for(Lookup lookup : port){
if(lookup.getId() == searchParams.getPort().getId()){
travelDetailReportBean.setPort(lookup.getDescEnglish());
break ;
}
}
}
else{
travelDetailReportBean.setPort(searchParams.getPort().getDescEnglish());
}
if(searchParams.getNationality().getId() != 0){
for(Lookup lookup : country){
if(lookup.getId() == searchParams.getNationality().getId()){
travelDetailReportBean.setCountry(lookup.getDescEnglish());
break ;
}
}
}
else{
travelDetailReportBean.setCountry(searchParams.getNationality().getDescEnglish());
}
if(searchParams.getVisaType().getId() != 0){
for(Lookup lookup : visaType){
if(lookup.getId() == searchParams.getVisaType().getId()){
travelDetailReportBean.setVisaType(lookup.getDescEnglish());
break ;
}
}
}
else{
travelDetailReportBean.setVisaType(searchParams.getVisaType().getDescEnglish());
}
logger.debug("nationality: " + travelDetailReportBean.getCountry());
logger.debug("travelType: " + travelDetailReportBean.getTravelType());
logger.debug("visatype: " + travelDetailReportBean.getVisaType());
logger.debug("port: " + travelDetailReportBean.getPort());
travelDetailReportBean.setReportName(BorderEntryExitConstants.TRAVEL_DETAIL_REPORT_NAME);
travelDetailReportBean.setReportPath(reportPath);
return travelDetailReportBean ;
}
The POJO code is shown below
public class TravelDetailReportBean extends ConcreteReportBean {
private String gender ;
private String travelType ;
private String port ;
private String country ;
private String visaType;
public String getGender() {
return gender;
}
public void setGender(String gender) {
if(gender == null || gender.equals("")){
this.gender="ALL";
}
else{
this.gender = gender;
}
}
public String getTravelType() {
return travelType;
}
public void setTravelType(String travelType) {
if(travelType == null || travelType.equals("")){
this.travelType ="ALL";
}
else{
this.travelType = travelType;
}
}
public String getPort() {
return port;
}
public void setPort(String port) {
if(port == null || port.equals("")){
this.port ="ALL";
}
else{
this.port = port;
}
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
if(country == null || country.equals("")){
this.country ="ALL";
}
else{
this.country = country;
}
}
public String getVisaType() {
return visaType;
}
public void setVisaType(String visaType) {
if(visaType == null || visaType.equals("")){
this.visaType ="ALL";
}
else{
this.visaType = visaType;
}
}
}
Issue is the generateReportBean method. i am putting to many if's to see if the id is not
zero get the description of that id from lookup else just set it like that and inside bean
setter i am checking for null. If null setting it to ALL.
My issue is currently i have few parameters and these if's can work for a while but what
if the search parameter grow. THe if's will look ugly. Can someone suggest me a better approach
to get rid of these if's.
Thanks,
Peter
If Lookup is List of objects then you can provide equals method based on id and then you can directly do
if(lookup.contains(searchParams.getTravelType()))
{
//code here
}
Follow Chain of Responsibility design pattern.
This will increase the code readability and maintainability
Reduces the number of "if" loops
Ref: http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
Divide the parsing pieces into different functions. eg.
checkgender(searchParams.getGender(), travelDetailReportBean);
or
travelDetailReportBean.setGender(checkgender(searchParams.getGender()));
Depends on how you want it
Yes you can put these methods into a utility class and do as Minion has suggested.
travelDetailReportBean.setGender(ParamUtil.checkGender(searchParams.getGender());
Putting validation condition in a dto as you have done is not a smart coding move. Is it a generic
parameter screen you are trying to make? Mostly, every report should have a separate parameter
screen if every report parameters differ.
HTH,
Ben
IMHO testing for empty/null Strings is too common to code it manually. I like to use StringUtils from Apache Commons lang to simplify it. Combined with Java's ? operator, you can write it much clearer:
private static final String OPTION_ALL = "ALL";
public void setGender(String gender) {
this.gender = StringUtils.isEmpty(gender) ? OPTION_ALL : gender;
}
Of course, if you have a large number of fields a generic approach may be justified.
EDIT: Conceptual consideration
As I see, you perform value checking in the classes setter methods. I would advise against doing so: I expect setters to only assign a value to an instance variable. If they do more, this might lead to confusion. You are probably using the class to parametrize some search function, so a better place for ensuring non-empty member values would be right before performing that search.
You may also annotate the fields that you need to do a lookup and then use a single loop to see their values in searchParams and if id is present, do a lookup.