Skip to content

Instantly share code, notes, and snippets.

@ralphcallaway
Created November 21, 2012 21:28
Show Gist options
  • Save ralphcallaway/4127887 to your computer and use it in GitHub Desktop.
Save ralphcallaway/4127887 to your computer and use it in GitHub Desktop.
Massive Internal View State (file extensions changed to assist with language auto-detection) See http://salesforce.stackexchange.com/questions/4537/how-to-reduce-a-large-internal-view-state-what-is-in-the-internal-view-state for related discussion
/* NB: Class has been edited for brevity and may not compile initially */
public with sharing class AccountView {
// Input Properties
public String filter1 { get; set; }
public String grouping1 { get; set; }
public String grouping2 { get; set; }
// Select Lists
public List<SelectOption> filter1Options { get; private set; }
public List<SelectOption> groupingOptions { get; private set; }
// Results
public List<Result> results { get; set; } { results = new List<Result>(); }
/* Constructor */
public AccountView() { }
/* Action Functions */
public PageReference doSelect() {
List<String> accountIds = getSelected(results);
/* Pass ids to the next page, section edited for brevity */
return nextPage;
}
public void doUpdate() {
buildResults(getAccounts());
}
/* Support Functions */
private void buildResults(List<Account> accounts) {
// collect groupings
List<Grouping> groupings = new List<Grouping>();
if(grouping1 != NONE_OPTION)
groupings.add(new Grouping(grouping1));
if(grouping2 != NONE_OPTION)
groupings.add(new Grouping(grouping2));
// group results
results = groupResults(groupings, accounts, existing);
}
private List<Account> getAccounts() {
String queryString = 'select **** from account where id != null';
/* Build up query string based on selected filters */
return Database.query(queryString);
}
// recursive get selected
private List<String> getSelected(List<Result> input) {
List<String> accountIds = new List<String>();
for(Result row : input) {
if(!row.isGrouping && row.selected) {
accountIds.add(row.recordId);
} else if(row.isGrouping) {
accountIds.addAll(getSelected(row.children));
}
}
return accountIds;
}
/* Grouping Functions */
// recurse starter
private static List<Result> groupResults(List<Grouping> groupings, List<Account> inputList, Set<Id> existing) {
List<Result> outputList = new List<Result>();
for(Account input : inputList) {
Result output = new Result(input);
if(existing.contains(input.id)) {
output.disabled = true;
output.selected = true;
}
outputList.add(output);
}
return groupResults(groupings, outputList);
}
// recursive processes selected grouping
private static List<Result> groupResults(List<Grouping> groupings, List<Result> inputList) {
// base case, just return the list without doing anything
if(groupings.isEmpty()) return inputList;
// pop next grouping
Grouping grouping = groupings[0];
groupings.remove(0);
// group results
Map<String, Result> resultMap = new Map<String, Result>();
for(Result input : inputList) {
Account account = input.record;
String label;
if(grouping.isLookup) {
label = (String) DynamicDMLHelper.recursiveGet(account, grouping.labelField);
} else {
label = (String) account.get(grouping.labelField);
}
if(label == null) {
label = BLANK_VALUE;
}
label = grouping.displayLabel + GROUP_NAME_SEPARATOR + label;
String value = (String) account.get(grouping.valueField);
if(value == null) {
value = BLANK_VALUE;
}
if(!resultMap.containsKey(value)) {
resultMap.put(value, new Result(label));
}
resultMap.get(value).children.add(input);
}
// flatten into grouping results
List<Result> outputList = new List<Result>();
List<String> sortedGroupings = new List<String>();
sortedGroupings.addAll(resultMap.keySet());
sortedGroupings.sort();
for(String sortedGrouping : sortedGroupings) {
outputList.add(resultMap.get(sortedGrouping));
}
// recurse on remaining groupings
for(Result output : outputList) {
output.children = groupResults(groupings.clone(), output.children);
}
// return result
return outputList;
}
/* Inner Classes */
private class Grouping {
// valueField = labelField for non lookup fields
String valueField; // field to look for value of grouping (e.g. parentId for parent account)
String labelField; // field to look for the label of the grouping (e.g parent.name for parent account)
String displayLabel; // label of the field for grouping (e.g. "Ownership Company" for ownership_company__c)
Boolean isLookup; // true if an id field
Grouping(String fieldApiName) {
fieldApiName = fieldApiName.toLowerCase(); // make the field api name case-insensitive
valueField = fieldApiName;
Schema.DescribeFieldResult fieldDescribe = accountFields.get(fieldApiName).getDescribe();
displayLabel = fieldDescribe.getLabel();
isLookup = fieldDescribe.getSOAPType() == Schema.SOAPType.ID;
if(isLookup) {
// "parentId" => "parent.name"
// "brand__c" => "brand__r.name"
labelField = fieldApiName.replaceAll('__c$','__r.name').replaceAll('id$','.name');
} else {
labelField = fieldApiName;
}
}
}
public Class Result {
public List<Result> children { get; private set; }
public Boolean disabled { get; private set; } { disabled = false; }
public Id recordId { get; private set; }
public Boolean isGrouping { get; private set; }
public String name { get; private set; }
public transient Account record { get; private set; }
public Boolean selected { get; set; } { selected = false; }
public Result(String name) {
this.name = name;
children = new List<Result>();
isGrouping = true;
}
public Result(Account record) {
this(record.name);
this.record = record;
recordId = record.id;
isGrouping = false;
}
}
}
<apex:page controller="AccountView" tabstyle="Account" title="Account View">
<apex:form >
<apex:pageBlock >
<!-- Filters for selecting accounts -->
<apex:facet name="header">
<apex:outputPanel layout="block">
<apex:panelGrid columns="3">
<apex:panelGroup >
<apex:outputLabel for="filter1" value="Filter 1: "/>
<apex:selectList id="filter1" value="{!filter1}" size="1">
<apex:selectOptions value="{!filter1Options}"/>
</apex:selectList>
</apex:panelGroup>
<!-- Additional Filters Excluded for Brevity -->
<!-- Results can be grouped in up to twol levels to better organize results and simplify selecting large numbers of accounts -->
<apex:panelGroup >
<apex:outputLabel for="grouping1" value="Grouping 1: "/>
<apex:selectList id="grouping1" value="{!grouping1}" size="1">
<apex:selectOptions value="{!groupingOptions}"/>
</apex:selectList>
</apex:panelGroup>
<apex:panelGroup >
<apex:outputLabel for="grouping2" value="Grouping 2: "/>
<apex:selectList id="grouping2" value="{!grouping2}" size="1">
<apex:selectOptions value="{!groupingOptions}"/>
</apex:selectList>
</apex:panelGroup>
</apex:panelGrid>
<apex:outputPanel layout="block" style="padding-top: 10px;">
<apex:commandButton value="Update Filters" action="{!doUpdate}" />
<apex:commandButton value="Select Accounts" action="{!doSelect}"/>
</apex:outputPanel>
</apex:outputPanel>
</apex:facet>
<apex:outputPanel layout="block">
<table class="list" style="border-collapse: collapse; width: 99%;">
<tr class="headerRow">
<td>Select</td>
<td>Name</td>
<td>Field 1</td>
<!-- Additional Fields excluded for brevity -->
</tr>
<!-- Level 1 Repeat -->
<apex:repeat value="{!results}" var="resLev1">
<tr>
<!-- Level 1 Group -->
<apex:outputPanel rendered="{!resLev1.isGrouping}">
<apex:outputPanel layout="none">
<td><input type="checkbox" onclick="javascript:(stuff to check all boxes in group)"/></td>
</apex:outputPanel>
<td colspan="3" class="grouping">{!resLev1.name} ({!resLev1.children.size})</td>
</apex:outputPanel>
<!-- Level 1 Results (displayed if no grouping) -->
<apex:outputPanel rendered="{!NOT(resLev1.isGrouping)}">
<apex:outputPanel layout="none" rendered="{!displaySelection}">
<td><apex:inputCheckbox value="{!resLev1.selected}"/></td>
</apex:outputPanel>
<td>
<apex:outputLink value="{!URLFOR($Action.Account.View, resLev1.record.id)}" target="_blank">
{!resLev1.name}
</apex:outputLink>
</td>
<td><apex:outputField value="{!resLev1.record.field1__c}"/></td>
<!-- Additional Fields excluded for brevity -->
</apex:outputPanel>
</tr>
<!-- Level 2 Repeat -->
<apex:repeat value="{!resLev1.children}" var="resLev2">
<tr>
<!-- Level 2 Group -->
<apex:outputPanel rendered="{!resLev2.isGrouping}">
<td colspan="3" class="grouping">{!resLev2.name} ({!resLev2.children.size})</td>
</apex:outputPanel>
<!-- Level 2 Results (displayed if only one grouping) -->
<apex:outputPanel rendered="{!NOT(resLev2.isGrouping)}">
<td><apex:inputCheckbox value="{!resLev2.selected}"/></td>
<td>
<apex:outputLink value="{!URLFOR($Action.Account.View, resLev2.record.id)}" target="_blank">
{!resLev2.name}
</apex:outputLink>
</td>
<td><apex:outputField value="{!resLev2.field1__c}"/></td>
<!-- Additional Fields excluded for brevity -->
</apex:outputPanel>
</tr>
<!-- Level 3 Repeat -->
<apex:repeat value="{!resLev2.children}" var="resLev3">
<tr>
<!-- Level 3 Result (can only group to two levels) -->
<td><apex:inputCheckbox value="{!resLev3.selected}"/></td>
<td>
<apex:outputLink value="{!URLFOR($Action.Account.View, resLev3.record.id)}" target="_blank">
{!resLev3.name}
</apex:outputLink>
</td>
<td><apex:outputField value="{!resLev3.field1__c}"/></td>
</tr>
</apex:repeat>
</apex:repeat>
</apex:repeat>
</table>
</apex:outputPanel>
</apex:pageBlock>
</apex:form>
</apex:page>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment