@NotNull
  public static List<SymfonyInstallerVersion> getVersions(@NotNull String jsonContent) {

    JsonObject jsonObject = new JsonParser().parse(jsonContent).getAsJsonObject();

    List<SymfonyInstallerVersion> symfonyInstallerVersions = new ArrayList<>();

    // prevent adding duplicate version on alias names
    Set<String> aliasBranches = new HashSet<>();

    // get alias version, in most common order
    for (String s : new String[] {"latest", "lts"}) {
      JsonElement asJsonObject = jsonObject.get(s);
      if (asJsonObject == null) {
        continue;
      }

      String asString = asJsonObject.getAsString();
      aliasBranches.add(asString);

      symfonyInstallerVersions.add(
          new SymfonyInstallerVersion(s, String.format("%s (%s)", asString, s)));
    }

    List<SymfonyInstallerVersion> branches = new ArrayList<>();
    Set<Map.Entry<String, JsonElement>> entries = jsonObject.entrySet();
    for (Map.Entry<String, JsonElement> entry : entries) {
      if (!entry.getKey().matches("^\\d+\\.\\d+$")) {
        continue;
      }

      // "2.8.0-dev", "2.8.0-DEV" is not supported
      String asString = entry.getValue().getAsString();
      if (asString.matches(".*[a-zA-Z].*") || aliasBranches.contains(asString)) {
        continue;
      }

      branches.add(
          new SymfonyInstallerVersion(
              asString, String.format("%s (%s)", entry.getKey(), asString)));
    }

    branches.sort(Comparator.comparing(SymfonyInstallerVersion::getVersion));

    Collections.reverse(branches);

    symfonyInstallerVersions.addAll(branches);

    // we need reverse order for sorting them on version string
    List<SymfonyInstallerVersion> installableVersions = new ArrayList<>();
    for (JsonElement installable : jsonObject.getAsJsonArray("installable")) {
      installableVersions.add(new SymfonyInstallerVersion(installable.getAsString()));
    }
    Collections.reverse(installableVersions);

    symfonyInstallerVersions.addAll(installableVersions);
    return symfonyInstallerVersions;
  }
 void insertInList(final List<MethodEntry> list, Comparator<MethodEntry> comparator) {
   boolean inserted = false;
   ListIterator li = list.listIterator();
   while (li.hasNext() && !inserted) {
     MethodEntry entry = ((MethodEntry) li.next());
     if (comparator.compare(this, entry) < 0) {
       LOG.debug(
           "insertInList dependent method: add "
               + myEnd.toString()
               + " at index "
               + (li.nextIndex() - 1));
       list.add(li.nextIndex() - 1, this);
       inserted = true;
     }
   }
   if (!inserted) {
     list.add(this);
   }
 }
 @SuppressWarnings("unchecked")
 @Override
 public int compare(final ElementNode o1, final ElementNode o2) {
   return myDelegate.compare((T) o1.getDelegate(), (T) o2.getDelegate());
 }
 private void setSortComparator(Comparator<ElementNode> sortComparator) {
   if (myComparator.equals(sortComparator)) return;
   myComparator = sortComparator;
   doSort();
 }
 @Override
 public int compare(VcsRef item1, VcsRef item2) {
   return myReferenceComparator.compare(item1, item2);
 }