# How to navigate multiple lists/maps and turn into string

I'm trying to populate a text field on Account with the Territory names of the account on insert or update (original territories, not Enterprise Territories or Territories2).

I've mapped through Account to Account Share to Group to Territory and have the correct territories but I can't seem to connect it back to the Account again.

Due to the AccountShare list inside the first map I am getting Incompatible key type List for Map at line 75 where I try to populate AccountTerritories__c (the text field on Account) with the correct territories. I tried vastly simplifying line 75 to just MapofTerritories.values(); (which I don't think would bulk at all) and got the error of Illegal assignment from List to String at line 75.

How can I get the correct territories linked with the correct Account ID and entered into the Text field?

trigger AccountTerritories on Account(before update) {
if (Trigger.isBefore) {
Set < Id > setOfAccountIds = new Set < Id > ();

for (Account acct: Trigger.New) {
if (Trigger.isUpdate) {
if (acct.Id != null) {
}
}
}

if (setOfAccountIds.size() > 0) {

/* Declaration of collection data types */
Map < id, List < AccountShare >> MapOfAccountShare = new Map < id, List < AccountShare >> ();
Map < Id, Id > mapOfGroup = new Map < Id, Id > ();
Map < Id, String > mapOfTerritories = new Map < Id, String > ();

//Query in Account Share object
/*
Those Accounts which are assigned via Territory Assignment Rules.
You can query those Accounts by filtering RowCause = 'Territory' in AccountShare object query.
*/
List < AccountShare > listOfAccountShare = [Select Id, UserOrGroupId, AccountId, RowCause from AccountShare where AccountId IN: setOfAccountIds];
System.debug('=== contents of listOfAccountShare: ' + listOfAccountShare);
System.debug('=== size of listOfAccountShare: ' + listOfAccountShare.size());
List < Id > Groupids = new List < Id > ();
for (AccountShare a: listofAccountShare) {
}

//Map of Account Share

for (AccountShare acctShare: listOfAccountShare) {
if (MapOfAccountShare.containsKey(acctShare.AccountID)) {
} else {
MapOfAccountShare.put(acctShare.AccountID, new List < AccountShare > {
acctShare
});
}
}
System.debug('=== all AccountShare keys in the map: ' + mapOfAccountShare.keySet());
System.debug('=== all AccountShare values in the map (as a List): ' + mapOfAccountShare.values());
System.debug('=== size of mapOfAccountShare: ' + mapOfAccountShare.size());

//Query in Group object
List < Group > listOfGroup = [Select Id, RelatedId from Group where Type = 'Territory'
and Id IN: GroupIDs
];
System.debug('=== contents of listOfGroup: ' + listOfGroup);
System.debug('=== size of listOfGroup: ' + listOfGroup.size());
//Map of Group object
for (Group groupRecord: listOfGroup) {
mapOfGroup.put(groupRecord.Id, groupRecord.RelatedId);
}
System.debug('=== all Group keys in the map: ' + mapOfGroup.keySet());
System.debug('=== all Group values in the map (as a List): ' + mapOfGroup.values());
System.debug('=== size of MapOfGroup: ' + mapOfGroup.size());

//Query in Territory object
List < Territory > listOfTerritory = [Select Id, Name from Territory where Id IN: mapOfGroup.Values()];
System.debug('=== contents of listOfTerritories: ' + listOfTerritory);
System.debug('=== size of listOfTerritories: ' + listOfTerritory.size());
//Map of Territory object

for (Territory Territories: listOfTerritory) {
mapOfTerritories.put(Territories.Id, Territories.Name);
System.debug('=== all Territories keys in the map: ' + mapOfTerritories.keySet());
System.debug('=== all Territories values in the map (as a List): ' + mapOfTerritories.values());
System.debug('=== size of MapOfTerritories: ' + mapOfTerritories.size());
}

for (Account updatedAccount: Trigger.new) {
String territory = MapofTerritories.values().get(mapofGroup.get(mapofAccountShare.get(updatedaccount.id)));
updatedAccount.territories = territory;
}

}

}
}

• What are you hoping to have in the territory String? In other words, how are you hoping to represent a List as a String? For example, do you want it to have a value of Germany,France,Italy? – Rob Aug 25 '15 at 14:18
• I think you need to go back to the drawing board with you objects and maps. The piece you are missing is how to relate the account back to the territories based on the account shares. Right now you have all of the info but there is nothing linking the data to the territories. All you have is a map of territories found as a result of the data but no way to relate it back to the data. Value() in your territories will be ALL territory names for ALL groups for ALL Accounts in the trigger currently – Eric Aug 25 '15 at 14:24
• I'd like it in a string like it shows up in the debug logs which looks like USER_DEBUG|[71]|DEBUG|=== all Territories values in the map (as a List): (Higher Education, HS Team, HS1) So Territories = Higher Education, HS Team, HS1 – user2769 Aug 25 '15 at 14:35
• So yes, I'm hoping to represent the List as a String with just the Territory Name Values. – user2769 Aug 25 '15 at 14:48

You have the below line inside of a for loop:

mapOfTerritories.put(Territories.Id, Territories.Name);


If you want a list of the Territory Names, you can just use

mapOfTerritories.values()


and assign that to a list.

You could also have created the list inside the original for loop where you created the map by simply doing something like this:

        list<string>terrlst = new list<string();

for (Territory Territories: listOfTerritory) {
mapOfTerritories.put(Territories.Id, Territories.Name);
System.debug('=== all Territories keys in the map: ' + mapOfTerritories.keySet());
System.debug('=== all Territories values in the map (as a List): ' + mapOfTerritories.values());
System.debug('=== size of MapOfTerritories: ' + mapOfTerritories.size());
}


Finally figured out how to get it mapped properly. Here's what I ended up with at the end to map back to the beginning and put in the Territory names.

for (Account updatedAccount : Trigger.new) {
List<AccountShare> accountSharesList = mapofAccountShare.get(updatedaccount.id);

String territories = '';
for (AccountShare accountshare : accountshareslist){ //loop through accountShares
// Get the group from the share
id groupid = accountshare.userorgroupid;
// Get the territory from the group map
id territoryid  = mapofGroup.get(groupid);
// Get the Territory Name from the territory Map
string TerritoryName = MapofTerritories.get(territoryid);
if(territoryname != null){
// Add next territory name to string of territories
territories = territories + territoryName +', ';// this is how i add the new territory to my string of territories
}
}
// remove last two chars here, but only if territories is not empty string
if(String.isNotBlank(territories)){
String TerritoryNames = Territories.Substring(0,Territories.length()-2);
updatedAccount.territories__c = TerritoryNames;
}