private void sortAllChoicesWithinDropdowns() {
    for (int i = 0; i < allChoices.size(); ++i) {
      SearchableFieldChoiceItem choiceItem = (SearchableFieldChoiceItem) allChoices.get(i);
      FieldSpec spec = choiceItem.getSpec();
      if (!spec.getType().isDropdown()) continue;

      DropDownFieldSpec dropdownSpec = (DropDownFieldSpec) spec;
      dropdownSpec.sortChoicesByLabel();
    }
  }
  public static boolean areDropDownChoicesMergeable(
      SearchableFieldChoiceItem choice1, SearchableFieldChoiceItem choice2) {
    FieldSpec rawSpec1 = choice1.getSpec();
    FieldSpec rawSpec2 = choice2.getSpec();
    if (!rawSpec1.getType().isDropdown()) return false;
    if (!rawSpec2.getType().isDropdown()) return false;
    if (!rawSpec1.getTag().equals(rawSpec2.getTag())) return false;
    if (!rawSpec1.getLabel().equals(rawSpec2.getLabel())) return false;

    DropDownFieldSpec spec1 = (DropDownFieldSpec) rawSpec1;
    DropDownFieldSpec spec2 = (DropDownFieldSpec) rawSpec2;
    return Arrays.equals(spec1.getReusableChoicesCodes(), spec2.getReusableChoicesCodes());
  }
  public ListOfReusableChoicesLists getCurrentDropdownChoices(DropDownFieldSpec spec) {
    ChoiceItem[] choices = spec.getAllChoices();

    String[] reusableChoicesCodes = spec.getReusableChoicesCodes();
    UiGrid dataSource = getGrid(spec);
    if (dataSource != null) {
      choices = getDataDrivenChoices(spec, dataSource);
    } else if (reusableChoicesCodes.length > 0) {
      return getReusableChoicesLists(reusableChoicesCodes);
    }

    ReusableChoices onlyChoices = new ReusableChoices("", "");
    onlyChoices.addAll(choices);
    return new ListOfReusableChoicesLists(onlyChoices);
  }
  public static SearchableFieldChoiceItem mergeDropDownChoices(
      SearchableFieldChoiceItem mergeInto, SearchableFieldChoiceItem mergeFrom) {
    if (!areDropDownChoicesMergeable(mergeInto, mergeFrom))
      throw new RuntimeException("Attempted to merge unmergeable fieldspecs");

    DropDownFieldSpec specInto = (DropDownFieldSpec) mergeInto.getSpec();
    DropDownFieldSpec specFrom = (DropDownFieldSpec) mergeFrom.getSpec();

    Vector choices = new Vector(Arrays.asList(specInto.getAllChoices()));
    ChoiceItem[] moreChoices = specFrom.getAllChoices();
    for (int i = 0; i < moreChoices.length; ++i) {
      if (!choices.contains(moreChoices[i])) choices.add(moreChoices[i]);
    }

    CustomDropDownFieldSpec resultSpec = new CustomDropDownFieldSpec();
    resultSpec.setTag(mergeInto.getSpec().getSubFieldTag());
    resultSpec.setLabel(mergeInto.getSpec().getLabel());
    resultSpec.setParent(mergeInto.getSpec().getParent());
    resultSpec.pullDynamicChoiceSettingsFrom(specFrom);
    // NOTE: Must setChoices AFTER pulling dynamic choices
    resultSpec.setChoices((ChoiceItem[]) choices.toArray(new ChoiceItem[0]));
    return new SearchableFieldChoiceItem(mergeInto.getSpecialCode(), resultSpec);
  }
  private UiGrid getGrid(DropDownFieldSpec spec) {
    String gridTag = spec.getDataSourceGridTag();
    if (gridTag == null) return null;

    return getGridField(gridTag);
  }
 private ChoiceItem[] getDataDrivenChoices(DropDownFieldSpec spec, UiGrid dataSource) {
   String gridColumnLabel = spec.getDataSourceGridColumn();
   return dataSource.buildChoicesFromColumnValues(gridColumnLabel);
 }