Skip to content

Commit

Permalink
Merge pull request #961 from ashitsalesforce/master
Browse files Browse the repository at this point in the history
polymorphic relationship mapping thru idlookup fields
  • Loading branch information
ashitsalesforce authored Feb 3, 2024
2 parents 06cc19f + 6af6176 commit b83695d
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -793,42 +793,41 @@ public void setFieldReferenceDescribes() throws ConnectionException {
continue;
}

boolean haSingleParentObject = parentObjectNames.length == 1;
if (parentObjectNames.length >= DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD) {
childObjectField.setLabel(childObjectField.getLabel() + " (Id)");
} else {
processParentObjectArrayForLookupReferences(parentObjectNames, childObjectField, haSingleParentObject);
processParentObjectArrayForLookupReferences(parentObjectNames, childObjectField);
}
}
}
}

private void processParentObjectArrayForLookupReferences(String[] parentObjectNames, Field childObjectField, boolean haSingleParentObject) throws ConnectionException {
private void processParentObjectArrayForLookupReferences(String[] parentObjectNames, Field childObjectField) throws ConnectionException {
for (int parentObjectIndex = 0; parentObjectIndex < parentObjectNames.length; parentObjectIndex++ ) {
String parentObjectName = parentObjectNames[parentObjectIndex];
processParentObjectForLookupReferences(parentObjectName, childObjectField, haSingleParentObject, parentObjectIndex, parentObjectNames.length);
processParentObjectForLookupReferences(parentObjectName, childObjectField, parentObjectIndex, parentObjectNames.length);
}
}

private void processParentObjectForLookupReferences(String parentObjectName, Field childObjectField, boolean haSingleParentObject, int parentObjectIndex, int totalParentObjects) throws ConnectionException {
private void processParentObjectForLookupReferences(String parentObjectName, Field childObjectField, int parentObjectIndex, int numParentTypes) throws ConnectionException {
Field[] parentObjectFields = describeSObject(parentObjectName).getFields();
Map<String, Field> parentIdLookupFieldMap = new HashMap<String, Field>();
for (Field parentField : parentObjectFields) {
processParentFieldForLookupReference(parentField, childObjectField, haSingleParentObject, parentObjectIndex, totalParentObjects, parentIdLookupFieldMap);
processParentFieldForLookupReference(parentField, childObjectField, numParentTypes, parentObjectIndex, numParentTypes, parentIdLookupFieldMap);
}
if (!parentIdLookupFieldMap.isEmpty()) {
DescribeRefObject describeRelationship = new DescribeRefObject(parentObjectName, childObjectField, parentIdLookupFieldMap);
referenceEntitiesDescribesMap.put(childObjectField.getRelationshipName(), describeRelationship);
}
}

private void processParentFieldForLookupReference(Field parentField, Field childObjectField, boolean haSingleParentObject, int parentObjectIndex, int totalParentObjects, Map<String, Field> parentIdLookupFieldMap) {
private void processParentFieldForLookupReference(Field parentField, Field childObjectField, int numParentTypes, int parentObjectIndex, int totalParentObjects, Map<String, Field> parentIdLookupFieldMap) {
if (!parentField.isIdLookup()) {
return;
}
if (parentField.getType() == FieldType.id) {
updateChildFieldLabelWithParentIdLabels(parentField, childObjectField, parentObjectIndex, totalParentObjects);
} else if (haSingleParentObject) {
} else if (numParentTypes <= DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD) {
parentIdLookupFieldMap.put(parentField.getName(), parentField);
}
}
Expand Down
27 changes: 15 additions & 12 deletions src/main/java/com/salesforce/dataloader/dyna/SforceDynaBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,24 @@ static public DynaProperty[] createDynaProps(DescribeSObjectResult describer, Co
// NOTE: currently only fields with one reference are supported on the server
FieldType fieldType = field.getType();
String relationshipName = field.getRelationshipName();
if (fieldType == FieldType.reference && field.getReferenceTo().length == 1 &&
if (fieldType == FieldType.reference && field.getReferenceTo().length <= DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD &&
relationshipName != null && relationshipName.length() > 0) {

DescribeRefObject parent = controller.getReferenceDescribes().getParentSObject(relationshipName);
if(parent != null) {
for(String refFieldName : parent.getParentObjectFieldMap().keySet()) {
// property name contains information for mapping
// add old format to dyna props
dynaProps.add(new DynaProperty(
RelationshipField.formatAsString(relationshipName, refFieldName),
for (String parentName : field.getReferenceTo()) {
RelationshipField relField = new RelationshipField(parentName, relationshipName);
DescribeRefObject parent = controller.getReferenceDescribes().getParentSObject(relField.toFormattedRelationshipString());
if(parent != null) {
for(String refFieldName : parent.getParentObjectFieldMap().keySet()) {
// property name contains information for mapping
// add old format to dyna props
dynaProps.add(new DynaProperty(
RelationshipField.formatAsString(relationshipName, refFieldName),
SObjectReference.class));
// add new format to dyna props
dynaProps.add(new DynaProperty(
RelationshipField.formatAsString(parent.getParentObjectName(), relationshipName, refFieldName),
SObjectReference.class));
// add new format to dyna props
dynaProps.add(new DynaProperty(
RelationshipField.formatAsString(parent.getParentObjectName(), relationshipName, refFieldName),
SObjectReference.class));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

Expand All @@ -52,10 +54,11 @@
public class ForeignKeyExternalIdPage extends LoadPage {

private final Map<String,Combo> extIdSelections = new HashMap<String,Combo>();
private final Map<String,Combo> parentSelections = new HashMap<String,Combo>();
private Composite containerComp;
private ScrolledComposite scrollComp;
private ReferenceEntitiesDescribeMap referenceObjects;
private int numChildFieldsWithNonIdLookupFieldSelections = 0;
private boolean hasParentEntitiesWithIdLookupField = false;


public ForeignKeyExternalIdPage(Controller controller) {
Expand Down Expand Up @@ -85,7 +88,7 @@ private void createFkExtIdUi() {
Composite comp = new Composite(scrollComp, SWT.NONE);
scrollComp.setContent(comp);

GridLayout gridLayout = new GridLayout(2, false);
GridLayout gridLayout = new GridLayout(3, false);
gridLayout.horizontalSpacing = 10;
gridLayout.marginHeight = 20;
gridLayout.verticalSpacing = 7;
Expand All @@ -99,9 +102,12 @@ private void createFkExtIdUi() {
scrollBar.setPageIncrement(20 * 5);

extIdSelections.clear();
this.numChildFieldsWithNonIdLookupFieldSelections = 0;
parentSelections.clear();
this.hasParentEntitiesWithIdLookupField = false;
if(referenceObjects != null) {
for(String relationshipName : referenceObjects.keySet()) {
List<String> sortedRelationshipList = new ArrayList<>(referenceObjects.keySet());
Collections.sort(sortedRelationshipList);
for(String relationshipName : sortedRelationshipList) {
OperationInfo operation = controller.getConfig().getOperationInfo();
Field childField = referenceObjects.getParentSObject(relationshipName).getChildField();
boolean isCreateableOrUpdateable = true;
Expand All @@ -123,7 +129,7 @@ private void createFkExtIdUi() {
}
if (isCreateableOrUpdateable) {
createObjectExtIdUi(comp, relationshipName);
numChildFieldsWithNonIdLookupFieldSelections++;
hasParentEntitiesWithIdLookupField = true;
}
}
}
Expand All @@ -137,27 +143,60 @@ private void createFkExtIdUi() {
* @param relationshipName
*/
private void createObjectExtIdUi(Composite comp, String relationshipName) {
Label labelExtId = new Label(comp, SWT.RIGHT);
DescribeRefObject extIdInfo = referenceObjects.getParentSObject(relationshipName);
labelExtId.setText(relationshipName);
labelExtId.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
RelationshipField relField = new RelationshipField(relationshipName, false);

// Add the ext id dropdown
Combo extIdCombo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY);
// Add parent dropdown
if (relField.getParentObjectName() == null) {
// shouldn't happen
return;
}
Combo parentCombo = this.parentSelections.get(relField.getRelationshipName());
if (parentCombo == null) {
// first parent object
Label labelExtId = new Label(comp, SWT.RIGHT);
labelExtId.setText(relField.getRelationshipName() + ":");
labelExtId.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));

parentCombo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY);
GridData parentData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
parentData.widthHint = 150;
parentCombo.setLayoutData(parentData);
parentCombo.add(relField.getParentObjectName());
parentCombo.select(0);
parentCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
String parentName = ((Combo)event.widget).getText();
Combo parentLookupIdFieldCombo = extIdSelections.get(relField.toFormattedRelationshipString());
parentLookupIdFieldCombo.removeAll();
RelationshipField selectedRelationship = new RelationshipField(parentName, relField.getRelationshipName());
populateParentLookupFieldCombo(parentLookupIdFieldCombo, selectedRelationship);
}
});
parentSelections.put(relField.getRelationshipName(), parentCombo);
// Add the ext id dropdown
Combo extIdCombo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY);

// The width comes out based on number of pixels, not characters
GridData extIdData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
extIdData.widthHint = 150;
extIdCombo.setLayoutData(extIdData);
// The width comes out based on number of pixels, not characters
GridData extIdData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
extIdData.widthHint = 150;
extIdCombo.setLayoutData(extIdData);
populateParentLookupFieldCombo(extIdCombo, relField);
extIdSelections.put(relField.toFormattedRelationshipString(), extIdCombo);
} else {
parentCombo.add(relField.getParentObjectName());
}
}

private void populateParentLookupFieldCombo(Combo extIdCombo, RelationshipField relField) {
DescribeRefObject extIdInfo = referenceObjects.getParentSObject(relField.toFormattedRelationshipString());

// get object's ext id info & set combo box to list of external id fields
// set the objects reference information
List<String> fieldList = new ArrayList<String>(extIdInfo.getParentObjectFieldMap().keySet());
// add default selection "not selected" to the list to allow users to go back to it
fieldList.add(Labels.getString("ForeignKeyExternalIdPage.defaultComboText"));
UIUtils.setComboItems(extIdCombo, fieldList, Labels.getString("ForeignKeyExternalIdPage.defaultComboText"));

extIdSelections.put(relationshipName, extIdCombo);
}

/**
Expand All @@ -184,36 +223,51 @@ private Map<String, Field> saveExtIdData() {
Map<String,Field> relatedFields = new HashMap<String,Field>();

// foreign key references (if any set)
Map<String,String> extIdReferences = new HashMap<String,String>();
for(String relationshipName : extIdSelections.keySet()) {
Combo combo = extIdSelections.get(relationshipName);
String extIdFieldName = combo.getText();
for(String relationshipNameInCombo : extIdSelections.keySet()) {
Combo combo = extIdSelections.get(relationshipNameInCombo);
String lookupFieldInParent = combo.getText();
RelationshipField relationshipField = getSelectedParentSObjectForLookupField(relationshipNameInCombo, lookupFieldInParent);
// make sure that the item selection has occurred and that the default text is not displayed anymore
if(extIdFieldName != null && extIdFieldName.length() > 0
&& ! extIdFieldName.equals(Labels.getString("ForeignKeyExternalIdPage.defaultComboText"))) {
DescribeRefObject refObjectInfo = referenceObjects.getParentSObject(relationshipName);
extIdReferences.put(relationshipName, RelationshipField.formatAsString(refObjectInfo.getParentObjectName(), extIdFieldName));
if(relationshipField != null) {
DescribeRefObject refDescribe = referenceObjects.getParentSObject(relationshipField.toFormattedRelationshipString());
Field relatedField = new Field();
Field parentField = refObjectInfo.getParentObjectFieldMap().get(extIdFieldName);
Field childField = refObjectInfo.getChildField();
RelationshipField relField = new RelationshipField(relationshipName, false);
relField.setParentFieldName(parentField.getName());
relatedField.setName(relField.toString());
Field parentField = refDescribe.getParentObjectFieldMap().get(lookupFieldInParent);
Field childField = refDescribe.getChildField();
relatedField.setName(relationshipField.toString());
String childFieldLabel = childField.getLabel();
String[] childFieldLabelParts = childFieldLabel.split(" \\(.+\\)$");
relatedField.setLabel(childFieldLabelParts[0] + " (" + parentField.getLabel() + ")");
relatedField.setCreateable(childField.isCreateable());
relatedField.setUpdateable(childField.isUpdateable());
relatedField.setType(FieldType.reference);
String[] refToArray = new String[1];
refToArray[0] = refObjectInfo.getParentObjectName();
refToArray[0] = refDescribe.getParentObjectName();
relatedField.setReferenceTo(refToArray);
relatedFields.put(relationshipName,relatedField);
relatedFields.put(relationshipField.toString(),relatedField);
}
}

return relatedFields;
}

private RelationshipField getSelectedParentSObjectForLookupField(String relationshipNameInCombo, String selectedIdLookupField) {
if(selectedIdLookupField != null && selectedIdLookupField.length() > 0
&& ! selectedIdLookupField.equals(Labels.getString("ForeignKeyExternalIdPage.defaultComboText"))) {
RelationshipField possibleParentSObjectField = new RelationshipField(relationshipNameInCombo, false);
Combo parentSObjectCombo = this.parentSelections.get(possibleParentSObjectField.getRelationshipName());
if (parentSObjectCombo == null) {
return null;
}
String actualParentSObjectName = parentSObjectCombo.getText();
String fullRelationshipName = RelationshipField.formatAsString(
actualParentSObjectName
, possibleParentSObjectField.getRelationshipName()
, selectedIdLookupField);
RelationshipField actualParentSObjectField = new RelationshipField(fullRelationshipName, true);
return actualParentSObjectField;
}
return null;
}

/*
* (non-Javadoc)
Expand Down Expand Up @@ -241,7 +295,7 @@ public void setPageComplete() {
@Override
protected OperationPage getNextPageOverride(){
setupPage();
if (numChildFieldsWithNonIdLookupFieldSelections == 0) {
if (!hasParentEntitiesWithIdLookupField) {
// nothing to display, go to the next page
return (OperationPage)getNextPage();
}
Expand All @@ -250,7 +304,7 @@ protected OperationPage getNextPageOverride(){

@Override
protected OperationPage getPreviousPageOverride(){
if (numChildFieldsWithNonIdLookupFieldSelections == 0) {
if (!hasParentEntitiesWithIdLookupField) {
// nothing to display, go to the previous page
return (OperationPage)getPreviousPage();
}
Expand Down

0 comments on commit b83695d

Please sign in to comment.