function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kenji775Kenji775 

Dynamic variable evaluation

Hey all,

I am writing a class there the exact condition of a loop will not be known ahead of time. I have a list of items, each item represents a field name. I need to loop over this list of field names, and evaluate the contents of the field that that item represents. In other languages you might do something like use eval()/evaluate() for handling dynmaic conditions, or use structure notation, but apex doesn't seem to allow for either. This is my code thus far.

 

 

public with sharing class eventClasses 
{
	public static void createScheduleObjects(events__c[] eventList)
	{
		//the idea here is to create all the required schedule objects for every event passed in.
		list<Employee_Schedule__c> Schedules = new List <Employee_Schedule__c>();
		
		//create a map of all the job types that exist. Every item here has a field by the same name
		//on the opportunity object that contains the number of people required to fill that role for this event.
		//the second part just contains a friendly name for this job to be shown to the user.
		Map<String,String> jobFieldList = new Map<String,String>();
		jobFieldList.put('Test_Set_up_Coordination__c','Test Setup');
		jobFieldList.put('Servers__c','Server');
		jobFieldList.put('Dishwasher__c','Dishwasher');
		jobFieldList.put('Kitchen__c','Kitchen');
		jobFieldList.put('Moderator__c','Moderator');
		
		//loop over every event passed in
		for(events__c event : eventList)
		{
			//For every job type defined, evaluate the number of people needed for that job as specified on the
			//related opportunity object
			for(String jobName : jobFieldList)
			{
				//ok, so now we are looking at one specific job (ex Dishwasher__c). There is a field on the 
				//related opportunity called Dishwasher__c. That field contains the number of employee schedule
				//objects we need to create for the Dishwasher__c type.
				
				//This line causes the error, I am unsure how to feed the jobName variable into this loop condition
				for(Integer i = 0; i< event.Project__r[jobName]; i++)
				{
					Employee_Schedule__c thisSchedule = new Employee_Schedule__c();
					thisSchedule.event__c = event.id;
					thisSchedule.Role__c = jobFieldList.get(jobName);
					Schedules.add(thisSchedule);
				}
			}
			
			
		}
		insert Schedules;
	}
}

 

 

I know this sounds kind of confusing, but really the issue itself isn't. In our instance we have 

Employee_Schedule__c -> Events__c -> Opportunity

 

When an event is created, we want to automatically create the schedules needed. The number and type of schedules needed is pulled from the Opportunity object, which has fields with the same names as the ones created in my jobFieldList. So when an event__c references project__r.Dishwasher__c that is a valid field that contains the number of people we need as dishwashers. So i need to create that many Employee_Schedule__c objects with the role set as Dishwasher.

 

The idea of course is to write clean code that simply iterate over a list of fields that contains numbers that tell it how many of that type of schedule record to create. Make sense? If so, how do I do it?! 

Best Answer chosen by Admin (Salesforce Developers) 
joshbirkjoshbirk

So if I'm understading:

 

 

  1. Opportunity is created with custom fields named after job roles with an integer of the number needed for that role.
  2. Events__c is associated with Opp, and each Event object has a child object which should equal all the integers of the role related field.  So if Dishwasher__c = 3, Chef__c = 3, there should be 6 Employee Schedules.
  3. And each of those 6 Employee Schedules has a job role field which tracks back to "Dishwasher" or "Chef".
I think using the "get" sObject method might get you where you need to go.  So total psuedocode:
Opportunity o = [SELECT ID, Chefs__c, Dishwashers__c FROM Opportunity];
for(i = 0; i < Integer.valueOf(o.get('Chefs__c')); i++) {
	 Schedule__c = new Schedule__c(Role=o.get('ChefsLabel__c'))
}

 

So you could set 'Chefs__c' and 'ChefsLabel__c' via a map/list of strings.  And then I think you just need to maintain the map/list of roles.

 

Make sense?

 

All Answers

joshbirkjoshbirk

So if I'm understading:

 

 

  1. Opportunity is created with custom fields named after job roles with an integer of the number needed for that role.
  2. Events__c is associated with Opp, and each Event object has a child object which should equal all the integers of the role related field.  So if Dishwasher__c = 3, Chef__c = 3, there should be 6 Employee Schedules.
  3. And each of those 6 Employee Schedules has a job role field which tracks back to "Dishwasher" or "Chef".
I think using the "get" sObject method might get you where you need to go.  So total psuedocode:
Opportunity o = [SELECT ID, Chefs__c, Dishwashers__c FROM Opportunity];
for(i = 0; i < Integer.valueOf(o.get('Chefs__c')); i++) {
	 Schedule__c = new Schedule__c(Role=o.get('ChefsLabel__c'))
}

 

So you could set 'Chefs__c' and 'ChefsLabel__c' via a map/list of strings.  And then I think you just need to maintain the map/list of roles.

 

Make sense?

 

This was selected as the best answer
Kenji775Kenji775

Yup, you were correct on all counts. I didn't know I could get an object value by using get (I suppose that is all too obvious now that I think about it). So in the end it looks like

 

 

			for(String jobName : jobFieldList.keySet())
			{
				//ok, so now we are looking at one specific job (ex Dishwasher__c). There is a field on the 
				//related opportunity called Dishwasher__c. That field contains the number of employee schedule
				//objects we need to create for the Dishwasher__c type.
				
				//This line causes the error, I am unsure how to feed the jobName variable into this loop condition
				integer iterator = Integer.valueOf(event.get(jobName));
				for(Integer i = 0; i< iterator; i++)
				{
					Employee_Schedule__c thisSchedule = new Employee_Schedule__c();
					thisSchedule.event__c = event.id;
					thisSchedule.Role__c = jobFieldList.get(jobName);
					thisSchedule.Punch_In__c = event.Start_Date__c;
					thisSchedule.Punch_Out2__c = event.End_Date__c;
					Schedules.add(thisSchedule);
				}
			}

 

 

The dynamic part  I was seeking is done by the 

 

integer iterator = Integer.valueOf(event.get(jobName));

 

I'll give my trigger a whack and see how it goes. Thanks a bunch for the tip, that's just what I needed (i think).

Kenji775Kenji775

It saves, but it errors, on this line

 

integer iterator = Integer.valueOf(event.get('project__r.'+jobName));

 

So while this works

 

 

system.debug(event.project__r.Moderator__c);
this fails
integer iterator = Integer.valueOf(event.get('project__r.moderator__c'));

 

joshbirkjoshbirk

is it possibly failing because Moderator__c could be null, which would bomb out valueOf (I think)?  Not sure if the Number needs the default value set to zero...

Kenji775Kenji775

You were correct, the value was null, but even with a value, it still bombs out. Full disclousre, this class is actually being invoked via a custom button click. The method that actually calls the one we are looking at looks like 

 

 

	WebService static void createSchedulesForEvent(string id)
	{
		list<events__c> thisEvent = [select id, 
											Start_Date__c, 
											End_Date__c, 
											project__c,
											project__r.Moderator__c
											from events__c where Id = :id];
		createScheduleObjects(thisEvent);
	}

 

 

later on I plan on making that query dynamic (also using that jobFieldList to tell it what projects values to pull, but for now I'm just hard coding them in). I doubt this is causing the issue, but just figured I'd try and help ya get a full grasp of whats going on.

 

joshbirkjoshbirk

If you're using the Eclipse ID, I'd put a valid Id into that SOQL and a System.debug on Integer.valueOf(thisEvent.get('project__r.Moderator__c')), and tool around with under Execute Anonymous.  When I first was playing around with the pseudocode, it reminded me I needed to use valueOf, for instance.  Might help narrow down the actual error...

Kenji775Kenji775

Thanks for the suggestion. I got something working, a hybrid between our two theories.

I just set it up to create a map of all references opportunities based on their id. for each event I find the right entry in the opportunity map, and use get(jobName) to extract the values required. Full code posted below.

 

Thank you so much for your help, couldn't have done it without ya.

 

 

global class eventClasses 
{
	WebService static void createSchedulesForEvent(string id)
	{
		list<events__c> thisEvent = [select id, 
											Start_Date__c, 
											End_Date__c, 
											project__c,
											project__r.Test_Set_up_Coordination__c,
											project__r.Servers__c,
											project__r.Dishwasher__c,
											project__r.Kitchen__c,
											project__r.Moderator__c
											from events__c where Id = :id];
		createScheduleObjects(thisEvent);
	}
	public static void createScheduleObjects(events__c[] eventList)
	{
		Map<Id,Opportunity> oppsMap = new Map<Id,Opportunity>();
		Set<Id> oppIds = new Set<Id>();
		
		for(events__c event : eventList)
		{
			oppIds.add(event.project__c);
		}

		for (Opportunity opp : [select id,
									   Test_Set_up_Coordination__c,
									   Servers__c,
									   Dishwasher__c,
									   Kitchen__c,
									   Moderator__c
									   from Opportunity where Id in :oppIds])
		{
			oppsMap.put(opp.id,opp);
		}
		
		//the idea here is to create all the required schedule objects for every event passed in.
		list<Employee_Schedule__c> Schedules = new List <Employee_Schedule__c>();
		
		list<Contact> SiteStaff = [select name, id from contact where account.name = 'FPI Field Ops'];
		
		//create a map of all the job types that exist. Every item here has a field by the same name
		//on the opportunity object that contains the number of people required to fill that role for this event.
		//the second part just contains a friendly name for this job to be shown to the user.
		Map<String,String> jobFieldList = new Map<String,String>();
		jobFieldList.put('Test_Set_up_Coordination__c','Test Setup');
		jobFieldList.put('Servers__c','Server');
		jobFieldList.put('Dishwasher__c','Dishwasher');
		jobFieldList.put('Kitchen__c','Kitchen');
		jobFieldList.put('Moderator__c','Moderator');
		
		//loop over every event passed in
		for(events__c event : eventList)
		{
			//For every job type defined, evaluate the number of people needed for that job as specified on the
			//related opportunity object
			for(String jobName : jobFieldList.keySet())
			{
				//ok, so now we are looking at one specific job (ex Dishwasher__c). There is a field on the 
				//related opportunity called Dishwasher__c. That field contains the number of employee schedule
				//objects we need to create for the Dishwasher__c type.
				
				//This line causes the error, I am unsure how to feed the jobName variable into this loop condition
				system.debug(event.project__r.Moderator__c);
				
				 
				Opportunity thisOpp = oppsMap.get(event.project__c);
				integer iterator = Integer.valueOf(thisOpp.get(jobName));
				for(Integer i = 0; i< iterator; i++)
				{
					Employee_Schedule__c thisSchedule = new Employee_Schedule__c();
					thisSchedule.event__c = event.id;
					thisSchedule.Role__c = jobFieldList.get(jobName);
					thisSchedule.Punch_In__c = event.Start_Date__c;
					thisSchedule.Punch_Out2__c = event.End_Date__c;
					Schedules.add(thisSchedule);
				}
			}
			
			
		}
		insert Schedules;
	}
}

 

 

simply buzzes 9simply buzzes 9
Awesom dude, great stuff and many thanks for your callaboration could you please have a look on Nangs Delivery (https://www.nangsdelivery.com/) and recommend me the best way to run this code please?