@Override
    public List<String> listPartitionNamesByValue(String databaseName, String tableName,
                                                  List<Optional<String>> partitionValues) {
        List<Partition> partitions = get(partitionCache, OdpsTableName.of(databaseName, tableName));
        ImmutableList.Builder<String> builder = ImmutableList.builder();
        if (partitions == null || partitions.isEmpty()) {
            return builder.build();
        }
        List<PartitionSpec> partitionSpecs =
                partitions.stream().map(Partition::getPartitionSpec).collect(Collectors.toList());
        List<String> keys = new ArrayList<>(partitionSpecs.get(0).keys());
        for (PartitionSpec partitionSpec : partitionSpecs) {
            boolean present = true;
            for (int index = 0; index < keys.size(); index++) {
                String value = keys.get(index);
                if (partitionValues.get(index).isPresent() && partitionSpec.get(value) != null) {
                    if (!partitionSpec.get(value).equals(partitionValues.get(index).get())) {
                        present = false;
                        break;
                    }
                }
            }
            if (present) {
                builder.add(partitionSpec.toString(false, true));
            }
        }
        return builder.build();
    }
@Test
    public void testListPartitionNamesByValue() {
        List<String> partitions = odpsMetadata.listPartitionNamesByValue("project", "tableName",
                ImmutableList.of(Optional.of("a"), Optional.empty()));
        Assert.assertEquals(Collections.singletonList("p1=a/p2=b"), partitions);

        partitions = odpsMetadata.listPartitionNamesByValue("project", "tableName",
                ImmutableList.of(Optional.empty(), Optional.of("b")));
        Assert.assertEquals(Collections.singletonList("p1=a/p2=b"), partitions);
    }