public void testMultipleAliasesPrecedence() throws Exception {
    client()
        .admin()
        .indices()
        .preparePutTemplate("template1")
        .setTemplate("*")
        .setOrder(0)
        .addAlias(new Alias("alias1"))
        .addAlias(new Alias("{index}-alias"))
        .addAlias(
            new Alias("alias3")
                .filter(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("test"))))
        .addAlias(new Alias("alias4"))
        .get();

    client()
        .admin()
        .indices()
        .preparePutTemplate("template2")
        .setTemplate("te*")
        .setOrder(1)
        .addAlias(new Alias("alias1").routing("test"))
        .addAlias(new Alias("alias3"))
        .get();

    assertAcked(
        prepareCreate("test").addAlias(new Alias("test-alias").searchRouting("test-routing")));

    ensureGreen();

    GetAliasesResponse getAliasesResponse =
        client().admin().indices().prepareGetAliases().addIndices("test").get();
    assertThat(getAliasesResponse.getAliases().get("test").size(), equalTo(4));

    for (AliasMetaData aliasMetaData : getAliasesResponse.getAliases().get("test")) {
      assertThat(
          aliasMetaData.alias(),
          anyOf(equalTo("alias1"), equalTo("test-alias"), equalTo("alias3"), equalTo("alias4")));
      if ("alias1".equals(aliasMetaData.alias())) {
        assertThat(aliasMetaData.indexRouting(), equalTo("test"));
        assertThat(aliasMetaData.searchRouting(), equalTo("test"));
      } else if ("alias3".equals(aliasMetaData.alias())) {
        assertThat(aliasMetaData.filter(), nullValue());
      } else if ("test-alias".equals(aliasMetaData.alias())) {
        assertThat(aliasMetaData.indexRouting(), nullValue());
        assertThat(aliasMetaData.searchRouting(), equalTo("test-routing"));
      }
    }
  }
    public static void toXContent(
        AliasMetaData aliasMetaData, XContentBuilder builder, ToXContent.Params params)
        throws IOException {
      builder.startObject(aliasMetaData.alias(), XContentBuilder.FieldCaseConversion.NONE);

      boolean binary = params.paramAsBoolean("binary", false);

      if (aliasMetaData.filter() != null) {
        if (binary) {
          builder.field("filter", aliasMetaData.filter.compressed());
        } else {
          byte[] data = aliasMetaData.filter().uncompressed();
          XContentParser parser = XContentFactory.xContent(data).createParser(data);
          Map<String, Object> filter = parser.mapOrdered();
          parser.close();
          builder.field("filter", filter);
        }
      }
      if (aliasMetaData.indexRouting() != null) {
        builder.field("index_routing", aliasMetaData.indexRouting());
      }
      if (aliasMetaData.searchRouting() != null) {
        builder.field("search_routing", aliasMetaData.searchRouting());
      }

      builder.endObject();
    }
  @Test
  public void testIndicesAliasesAcknowledgement() {
    createIndex("test");

    // testing acknowledgement when trying to submit an existing alias too
    // in that case it would not make any change, but we are sure about the cluster state
    // as the previous operation was acknowledged
    for (int i = 0; i < 2; i++) {
      assertAcked(client().admin().indices().prepareAliases().addAlias("test", "alias"));

      for (Client client : clients()) {
        AliasMetaData aliasMetaData =
            ((AliasOrIndex.Alias)
                    getLocalClusterState(client).metaData().getAliasAndIndexLookup().get("alias"))
                .getFirstAliasMetaData();
        assertThat(aliasMetaData.alias(), equalTo("alias"));
      }
    }
  }
 public static void writeTo(AliasMetaData aliasMetaData, StreamOutput out) throws IOException {
   out.writeString(aliasMetaData.alias());
   if (aliasMetaData.filter() != null) {
     out.writeBoolean(true);
     aliasMetaData.filter.writeTo(out);
   } else {
     out.writeBoolean(false);
   }
   if (aliasMetaData.indexRouting() != null) {
     out.writeBoolean(true);
     out.writeString(aliasMetaData.indexRouting());
   } else {
     out.writeBoolean(false);
   }
   if (aliasMetaData.searchRouting() != null) {
     out.writeBoolean(true);
     out.writeString(aliasMetaData.searchRouting());
   } else {
     out.writeBoolean(false);
   }
 }
  /**
   * Finds the specific index aliases that match with the specified aliases directly or partially
   * via wildcards and that point to the specified concrete indices or match partially with the
   * indices via wildcards.
   *
   * @param aliases The names of the index aliases to find
   * @param concreteIndices The concrete indexes the index aliases must point to order to be
   *     returned.
   * @return the found index aliases grouped by index
   */
  public ImmutableOpenMap<String, List<AliasMetaData>> findAliases(
      final String[] aliases, String[] concreteIndices) {
    assert aliases != null;
    assert concreteIndices != null;
    if (concreteIndices.length == 0) {
      return ImmutableOpenMap.of();
    }

    boolean matchAllAliases = matchAllAliases(aliases);
    ImmutableOpenMap.Builder<String, List<AliasMetaData>> mapBuilder = ImmutableOpenMap.builder();
    Iterable<String> intersection =
        HppcMaps.intersection(ObjectHashSet.from(concreteIndices), indices.keys());
    for (String index : intersection) {
      IndexMetaData indexMetaData = indices.get(index);
      List<AliasMetaData> filteredValues = new ArrayList<>();
      for (ObjectCursor<AliasMetaData> cursor : indexMetaData.getAliases().values()) {
        AliasMetaData value = cursor.value;
        if (matchAllAliases || Regex.simpleMatch(aliases, value.alias())) {
          filteredValues.add(value);
        }
      }

      if (!filteredValues.isEmpty()) {
        // Make the list order deterministic
        CollectionUtil.timSort(
            filteredValues,
            new Comparator<AliasMetaData>() {
              @Override
              public int compare(AliasMetaData o1, AliasMetaData o2) {
                return o1.alias().compareTo(o2.alias());
              }
            });
        mapBuilder.put(index, Collections.unmodifiableList(filteredValues));
      }
    }
    return mapBuilder.build();
  }
  /**
   * Checks if at least one of the specified aliases exists in the specified concrete indices.
   * Wildcards are supported in the alias names for partial matches.
   *
   * @param aliases The names of the index aliases to find
   * @param concreteIndices The concrete indexes the index aliases must point to order to be
   *     returned.
   * @return whether at least one of the specified aliases exists in one of the specified concrete
   *     indices.
   */
  public boolean hasAliases(final String[] aliases, String[] concreteIndices) {
    assert aliases != null;
    assert concreteIndices != null;
    if (concreteIndices.length == 0) {
      return false;
    }

    Iterable<String> intersection =
        HppcMaps.intersection(ObjectHashSet.from(concreteIndices), indices.keys());
    for (String index : intersection) {
      IndexMetaData indexMetaData = indices.get(index);
      List<AliasMetaData> filteredValues = new ArrayList<>();
      for (ObjectCursor<AliasMetaData> cursor : indexMetaData.getAliases().values()) {
        AliasMetaData value = cursor.value;
        if (Regex.simpleMatch(aliases, value.alias())) {
          filteredValues.add(value);
        }
      }
      if (!filteredValues.isEmpty()) {
        return true;
      }
    }
    return false;
  }
 public Builder putAlias(AliasMetaData aliasMetaData) {
   aliases.put(aliasMetaData.alias(), aliasMetaData);
   return this;
 }
 public Builder(AliasMetaData aliasMetaData) {
   this(aliasMetaData.alias());
   filter = aliasMetaData.filter();
   indexRouting = aliasMetaData.indexRouting();
   searchRouting = aliasMetaData.searchRouting();
 }