Skip to content

Commit

Permalink
support lookup using non-createable/non-modifiable parent field
Browse files Browse the repository at this point in the history
support relationship lookup using non-createable/non-modifiable parent field such as an autonumber field marked as an external id.
  • Loading branch information
ashitsalesforce committed Oct 15, 2023
1 parent 9681016 commit 2b8ef77
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class DescribeRefObject {
this.childField = childField;
}

public Map<String, Field> getFieldInfoMap() {
public Map<String, Field> getParentObjectFieldMap() {
return parentFieldInfoMap;
}

Expand Down
43 changes: 18 additions & 25 deletions src/main/java/com/salesforce/dataloader/client/PartnerClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -788,23 +788,22 @@ public void setFieldReferenceDescribes() throws ConnectionException {
Field[] entityFields = getFieldTypes().getFields();
String entityName = this.config.getString(Config.ENTITY);

for (Field entityField : entityFields) {
for (Field childObjectField : entityFields) {
// upsert on references (aka foreign keys) is supported only
// 1. When field has relationship is set and refers to exactly one object
// 2. When field is either createable or updateable. If neither is true, upsert will never work for that
// relationship.
if (entityField.isCreateable() || entityField.isUpdateable()) {
String relationshipName = entityField.getRelationshipName();
String[] parentObjectNames = entityField.getReferenceTo();
if (childObjectField.isCreateable() || childObjectField.isUpdateable()) {
String relationshipName = childObjectField.getRelationshipName();
String[] parentObjectNames = childObjectField.getReferenceTo();
boolean haSingleParentObject = parentObjectNames.length == 1;
if (parentObjectNames != null
&& parentObjectNames.length >= DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD) {
entityField.setLabel(entityField.getLabel() + " (Id)");
childObjectField.setLabel(childObjectField.getLabel() + " (Id)");
}
if (parentObjectNames != null && parentObjectNames.length > 0 && parentObjectNames[0] != null
&& relationshipName != null && relationshipName.length() > 0
&& parentObjectNames.length < DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD
&& (entityField.isCreateable() || entityField.isUpdateable())) {
&& parentObjectNames.length < DescribeRefObject.MAX_PARENT_OBJECTS_IN_REFERENCING_FIELD) {

for (int parentObjectIndex = 0; parentObjectIndex < parentObjectNames.length; parentObjectIndex++ ) {
String parentObjectName = parentObjectNames[parentObjectIndex];
Expand All @@ -818,7 +817,7 @@ public void setFieldReferenceDescribes() throws ConnectionException {
if (parentField.getType() == FieldType.id) {
// add parents' id field labels in parenthesis to the child's
// field label.
String childFieldLabel = entityField.getLabel();
String childFieldLabel = childObjectField.getLabel();
String[] childFieldLabelParts = childFieldLabel.split(" \\(.+\\)$");
childFieldLabel = childFieldLabelParts[0];
if (parentObjectIndex == 0) {
Expand All @@ -830,27 +829,15 @@ public void setFieldReferenceDescribes() throws ConnectionException {
if (parentObjectIndex == parentObjectNames.length - 1) {
childFieldLabel = childFieldLabel + ")";
}
entityField.setLabel(childFieldLabel);
childObjectField.setLabel(childFieldLabel);
} else if (haSingleParentObject) { // nonId lookup field on the parent entity
if (!entityName.equalsIgnoreCase(parentObjectName)) {
// Change createable and updateable attributes of a reference field
// only if it is not a self-reference.
//
// The conditional check is to address the issue [W-10811419]:
// Name (Auto-Number - a read-only field) field shows up in mapping dialog
// when parent entity is the same as child entity (self-ref) because
// the field's "isUpdateable" attribute may get changed from "false"
// to "true" in the following code.
parentField.setCreateable(entityField.isCreateable());
parentField.setUpdateable(entityField.isUpdateable());
}
parentFieldInfo.put(parentField.getName(), parentField);
}
}
}
if (!parentFieldInfo.isEmpty()) {
DescribeRefObject describe = new DescribeRefObject(parentObjectName, entityField, parentFieldInfo);
referenceDescribes.put(relationshipName, describe);
DescribeRefObject describeRelationship = new DescribeRefObject(parentObjectName, childObjectField, parentFieldInfo);
referenceDescribes.put(relationshipName, describeRelationship);
}
}
}
Expand Down Expand Up @@ -969,9 +956,15 @@ private Field lookupField(String apiName) {
for (Map.Entry<String, DescribeRefObject> ent : refs.entrySet()) {
String relName = ent.getKey().toLowerCase();
if (apiName.startsWith(relName)) {
for (Map.Entry<String, Field> refEntry : ent.getValue().getFieldInfoMap().entrySet()) {
for (Map.Entry<String, Field> refEntry : ent.getValue().getParentObjectFieldMap().entrySet()) {
String thisRefName = relName + ":" + refEntry.getKey().toLowerCase();
if (apiName.equals(thisRefName)) return refEntry.getValue();
if (apiName.contains(".")) {
thisRefName = relName + ":"
+ ent.getValue().getParentObjectName()
+ "." + refEntry.getKey().toLowerCase();
}

if (apiName.equalsIgnoreCase(thisRefName)) return refEntry.getValue();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void addReferenceToSObject(Controller controller, SObject sObj, String re
// set entity type, has to be set before all others
sObjRef.setType(entityRefInfo.getParentObjectName());
// set external id, do type conversion as well
Class typeClass = SforceDynaBean.getConverterClass(entityRefInfo.getFieldInfoMap().get(fieldName));
Class typeClass = SforceDynaBean.getConverterClass(entityRefInfo.getParentObjectFieldMap().get(fieldName));
Object extIdValue = ConvertUtils.convert(this.referenceExtIdValue.toString(), typeClass);
sObjRef.setField(fieldName, extIdValue);
// Add the sObject reference as a child elemetn, name set to relationshipName
Expand Down Expand Up @@ -101,7 +101,7 @@ public Object getReferenceExtIdValue() {

public static String getRelationshipField(Controller controller, String refFieldName) {
final String relName = new ObjectField(refFieldName).getObjectName();
controller.getReferenceDescribes().get(relName).getFieldInfoMap();
controller.getReferenceDescribes().get(relName).getParentObjectFieldMap();
for (Field f : controller.getFieldTypes().getFields()) {
if (f != null) {
if (relName.equals(f.getRelationshipName())) { return f.getName(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static public DynaProperty[] createDynaProps(DescribeSObjectResult describer, Co

DescribeRefObject refInfo = controller.getReferenceDescribes().get(relationshipName);
if(refInfo != null) {
for(String refFieldName : refInfo.getFieldInfoMap().keySet()) {
for(String refFieldName : refInfo.getParentObjectFieldMap().keySet()) {
// property name contains information for mapping
dynaProps.add(new DynaProperty(ObjectField.formatAsString(relationshipName, refFieldName),
SObjectReference.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private void createObjectExtIdUi(Composite comp, String relationshipName) {

// 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.getFieldInfoMap().keySet());
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"));
Expand Down Expand Up @@ -193,7 +193,7 @@ private Map<String, Field> saveExtIdData() {
DescribeRefObject refObjectInfo = referenceObjects.get(relationshipName);
extIdReferences.put(relationshipName, ObjectField.formatAsString(refObjectInfo.getParentObjectName(), extIdFieldName));
Field relatedField = new Field();
Field parentField = refObjectInfo.getFieldInfoMap().get(extIdFieldName);
Field parentField = refObjectInfo.getParentObjectFieldMap().get(extIdFieldName);
Field childField = refObjectInfo.getChildField();
relatedField.setName(relationshipName + ":" + parentField.getName());
String childFieldLabel = childField.getLabel();
Expand Down

0 comments on commit 2b8ef77

Please sign in to comment.