[SalesForce] REST API: How to update active values for picklist

I need to update the Picklist values for a custom field on a custom object. I have already populated the Available Values via the Enterprise and Metadata Java APIs, but now I need to move the newly updated Available Values to the Selected Values Picklist.

I can query the custom field as described in this post:

REST API: How to retrieve active values for picklist?

Does anyone have an example of doing this via the Enterprise/Metadata APIs?

Update:

This is the code that I use to update the picklist using the Salesforce API. This only updates the Available Values and not the Selected Values of the Picklist:

/** Updates the versions in Salesforce. */
public void updateSalesforceVersions() throws ConnectionException, InterruptedException
{
  // Salesforce object and field name values
  String sObjectName = "Product_Information__c";
  String fieldName = "Licensed_Version__c";
  String fullName = String.format("%s.%s", sObjectName, fieldName);

  List<OhmVersion> versionsFromDao = this.getOhmVersions();

  Field versionsField = SalesforceUtilities.getField(
    salesforceConnectionSource.getConnection().getEnterpriseConnection(),
    FieldType.picklist, sObjectName, fieldName);

  if(versionsField == null)
    return;

  Picklist versionsPicklist = new Picklist();
  List<PicklistValue> versionsPicklistValues = new ArrayList<>();
  for (OhmVersion version : versionsFromDao)
  {
    PicklistValue picklistValue = new PicklistValue();
    picklistValue.setFullName(version.getVersion());
    versionsPicklistValues.add(picklistValue);
  }
  versionsPicklist.setPicklistValues(versionsPicklistValues.toArray(
    new PicklistValue[versionsPicklistValues.size()]));

  CustomField customField = new CustomField();
  customField.setFullName(fullName);
  customField.setType(com.sforce.soap.metadata.FieldType.Picklist);
  customField.setLabel(versionsField.getLabel());
  customField.setPicklist(versionsPicklist);

  AsyncResult asyncResult = SalesforceUtilities.updateCustomField(
  salesforceConnectionSource.getConnection().getMetadataConnection(),
  fullName, customField);
}

This is the code that actually updates the picklist metadata:

public static AsyncResult updateCustomField(MetadataConnection metadataConnection,
                                            String fullName, 
                                            CustomField customField) 
  throws ConnectionException, InterruptedException
{
  AsyncResult asyncResult = new AsyncResult();

  // do the update
  UpdateMetadata updateMetadata = new UpdateMetadata();
  updateMetadata.setMetadata(customField);
  updateMetadata.setCurrentName(fullName);

  // wait for it to complete
  AsyncResult[] ars = metadataConnection.update(new UpdateMetadata[] {
    updateMetadata });
  asyncResult = ars[0];

  // set initial wait time to one second
  long waitTimeMilliSecs = 1000;
  while(!asyncResult.isDone())
  {
    Thread.sleep(waitTimeMilliSecs);
    // double the wait time for the next iteration
    waitTimeMilliSecs *= 2;
    asyncResult = metadataConnection.checkStatus(new String[] { asyncResult.getId()})[0];
  }
  return asyncResult;
}

This only updates the Available Values. I don't see any method or property to update the Selected Values. I can query the Selected Values with this code by using the EnterpriseConnection.describeLayout() method:

public void describeLayout()
{
  String sObjectName = PRODUCT_INFORMATION;
  try
  {
    // Make the describe call
    DescribeLayoutResult describeLayoutResult = 
        this.enterpriseConnection.describeLayout(sObjectName,
                             new String[] { SalesforceConstants.PRODUCT_INFORMATION_OHM_RECORD_TYPE_ID });
    // Get sObject metadata
    if (describeLayoutResult != null)
    {
      for(RecordTypeMapping recordTypeMapping : describeLayoutResult.getRecordTypeMappings())
      {
        System.out.println("RecordTypeMap name: " + recordTypeMapping.getName());
        for(PicklistForRecordType picklistForRecordType : recordTypeMapping.getPicklistsForRecordType())
        {
          System.out.println("Picklist Name:" + picklistForRecordType.getPicklistName());
          for(PicklistEntry entry : picklistForRecordType.getPicklistValues())
          {
            System.out.println("Entry Value:" + entry.getValue());
          }
          System.out.println();
        }
        System.out.println();
      }
    }
  }
  catch (ConnectionException ce)
  {
    fail("Connection failed: " + ce);
  }
}

How do I update the Selected Values even if I need to use a different class/method?

Best Answer

I was finally able to figure it out. It was a combination of using the RecordType with the metadata.update() call:

public void recordTypeSample() throws InterruptedException
{
  try
  {
    RecordType productInfo = new RecordType();
    productInfo.setFullName("Product_Information__c.OHM");
    productInfo.setLabel("OHM");

    PicklistValue version1 = new PicklistValue();
    version1.setFullName("7.4.5");

    RecordTypePicklistValue ohmVersions = new RecordTypePicklistValue();
    ohmVersions.setPicklist("Licensed_Version__c");
    ohmVersions.setValues(new PicklistValue[] { version1 });
    productInfo.setPicklistValues(new RecordTypePicklistValue[] { ohmVersions });

    UpdateMetadata updateMetadata = new UpdateMetadata();
    updateMetadata.setMetadata(productInfo);
    updateMetadata.setCurrentName(productInfo.getFullName());

    AsyncResult[] asyncResults = this.metadataConnection.update(new UpdateMetadata[] { updateMetadata });

    AsyncResult asyncResult = asyncResults[0];

    // set initial wait time to one second
    long waitTimeMilliSecs = 1000;
    while(!asyncResult.isDone())
    {
      Thread.sleep(waitTimeMilliSecs);
      // double the wait time for the next iteration
      waitTimeMilliSecs *= 2;
      asyncResult = metadataConnection.checkStatus(new String[] { asyncResult.getId() })[0];
    }
  }
  catch(ConnectionException ce)
  {
    ce.printStackTrace();
  }
}