Here's my stab at what I think you're trying to do:
public class GlobalIds {
public list<sObject> generateGlobal_Id_Generator(list<sObject> TheRecords){
if(!TheRecords.isEmpty()){
// I guess you mean to check that each element matches the sObjectType
// reported by the list, so...
for(sObject Record : TheRecords) {
system.assertEquals(TheRecords.getSObjectType(),Record.getSObjectType());
}
return getGlobal_Ids(TheRecords, TheRecords[0].getSObjectType());
}else{
Throw new CustomIdGenerationListIsEmptyException();
}
}
public list<sObject> getGlobal_Ids(list<sObject> TheRecords, Schema.SObjectType objectType){
for(SObject Record:TheRecords){
// Using .put() instead of assignment because it's a generic sObject
// Using objectType.getDescribe().getName() because we've already checked that
// the sObjectType is correct
Record.put('Global_Id__c', getGlobal_Id(objectType.getDescribe().getName(), Id.ValueOf(Record.Id)));
}
return TheRecords;
}
// Mocks so that I can compile this
public String getGlobal_Id(String objName, Id objId) {
return objName + objId;
}
public class CustomIdGenerationListIsEmptyException extends Exception {
}
}
I'm not sure that I can explain much more than just what's in the comments, but happy to answer questions on it. Or be told that I missed the point ;-)
So I made a Map fieldTypeMap and a component to handle the date/datetime format
Here is what I did, maybe it will be usefull for someone else.
Controller
I added the map as an attribute of my inner class into the controller:
// header/type mapping
public Map<String,String> headerTypeMap {get;set;}
I initialize it at the end of the constructor, thanks to this.headers (array of string header/field name), after the queries, like this:
// calculation :
runQueries();
// mapping
this.headerTypeMap = new Map<String,String>();
for(String field : this.headers){
this.headerTypeMap.put(
field,
Schema.getGlobalDescribe().get(objType).getDescribe().fields.getMap().get(field).getDescribe().getType()+''
);
}
Visualforce component
Because I often need to format date and datetime I thought it could be a good idea to create a formating component
So I made a quick and dirty one:
<apex:component controller="FormatedValueController">
<apex:attribute name="dateValue"
type="Date"
assignTo="{!inputDateValue}"
description="input value to formatTodoBlock__c record that contains data"
/>
<apex:attribute name="datetimeValue"
type="Date"
assignTo="{!inputDateTimeValue}"
description="input value to formatTodoBlock__c record that contains data"
/>
{!formatedvalue}
Controller:
public class FormatedValueController {
public Date inputDateValue {get;set;}
public Datetime inputDateTimeValue {get;set;}
public String getFormatedValue(){
String formatedValue = '';
formatedValue += inputDateValue == null ? '' : inputDateValue.format();
formatedValue += inputDateTimeValue == null ? '' : inputDateTimeValue.format();
return formatedValue;
}
}
And a quick&dirty test class too (for code coverage only):
@isTest
global class FormatedValueController_test{
static testMethod void FormatedValueController() {
FormatedValueController c = new FormatedValueController();
Test.startTest ();
c.getFormatedValue();
Test.stopTest();
}
}
100% you-hou ;)
And finally ...
Main Component
Oddly I need to use "{!todoBlock.headerTypeMap[header]}" everywhere, where todoBlock is the instance of my innerclass and header the var of repeat on headers attribute (table with a dynamic number of columns).
I wanted to use an apex variable for each header, kind of:
<apex:variable var="type" value="{!todoBlock.headerTypeMap[header]}" />
but for an unknown reason it just display the last header value in every loop. For example if I have DATE, DATETIME, STRING, it displays STRING, STRING, STRING. Not a big deal to use the full code, it is just less readable.
So here it is :
<apex:outputLabel rendered="{!todoBlock.headerTypeMap[header]=='DATETIME'}">
<c:FormatedValue datetimeValue="{!rec[header]}"/>
</apex:outputLabel>
<apex:outputLabel rendered="{!todoBlock.headerTypeMap[header]=='DATE'}">
<c:FormatedValue dateValue="{!rec[header]}"/>
</apex:outputLabel>
<apex:outputLabel rendered="{!NOT(AND(todoBlock.headerTypeMap[header]=='DATETIME',todoBlock.headerTypeMap[header]=='DATE'))}">
{!rec[header]}
</apex:outputLabel>
Best Answer
Apex requires types to be known at compile time to directly reference fields.
But there are are
get
methods in the SObject class for this case where the field names can be used in string form:but it is up to you to cast to the correct type as the return value of
get
isObject
.