• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Libphonenumber Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.i18n.phonenumbers.metadata.table;
17 
18 import com.google.auto.value.AutoValue;
19 import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.Maps;
21 import java.util.ArrayList;
22 import java.util.Comparator;
23 import java.util.EnumSet;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.function.Function;
27 import java.util.stream.Stream;
28 
29 /** Key for use in "diff" tables, allowing rows to be marked with a diff status. */
30 @AutoValue
31 public abstract class DiffKey<K> {
32   /**
33    * Status for rows in a "diff table". Every row in a diff table has a {@code DiffKey}, with a
34    * status. Modified rows appear twice in the diff table, once for the left-side row, and once for
35    * the right-side row.
36    */
37   public enum Status {
38     /** A row which appears exclusively in the left-hand-side of the diff. */
39     LHS_ONLY("----"),
40     /** A row which appears exclusively in the right-hand-side of the diff. */
41     RHS_ONLY("++++"),
42     /** The left-hand-side row which was modified by the  diff. */
43     LHS_CHANGED("<<<<"),
44     /** The right-hand-side row which was modified by the diff. */
45     RHS_CHANGED(">>>>"),
46     /** A row unchanged by the diff. */
47     UNCHANGED("====");
48 
49     private static final ImmutableMap<String, Status> MAP =
50         Maps.uniqueIndex(EnumSet.allOf(Status.class), Status::getLabel);
51 
52     private final String label;
53 
Status(String label)54     Status(String label) {
55       this.label = label;
56     }
57 
getLabel()58     String getLabel() {
59       return label;
60     }
61 
parse(String s)62     static Status parse(String s) {
63       return MAP.get(s);
64     }
65   }
66 
wrap(CsvKeyMarshaller<K> keyMarshaller)67   static <K> CsvKeyMarshaller<DiffKey<K>> wrap(CsvKeyMarshaller<K> keyMarshaller) {
68     List<String> keyColumns = new ArrayList<>();
69     keyColumns.add("Diff");
70     keyColumns.addAll(keyMarshaller.getColumns());
71     return new CsvKeyMarshaller<>(
72         serialize(keyMarshaller), deserialize(keyMarshaller), ordering(keyMarshaller), keyColumns);
73   }
74 
of(Status status, K key)75   static <K> DiffKey<K> of(Status status, K key) {
76     return new AutoValue_DiffKey<>(status, key);
77   }
78 
getStatus()79   public abstract Status getStatus();
80 
getOriginalKey()81   public abstract K getOriginalKey();
82 
serialize(CsvKeyMarshaller<T> m)83   private static <T> Function<DiffKey<T>, Stream<String>> serialize(CsvKeyMarshaller<T> m) {
84     return k -> Stream.concat(Stream.of(k.getStatus().getLabel()), m.serialize(k.getOriginalKey()));
85   }
86 
deserialize(CsvKeyMarshaller<T> m)87   private static <T> Function<List<String>, DiffKey<T>> deserialize(CsvKeyMarshaller<T> m) {
88     return r ->
89         new AutoValue_DiffKey<>(Status.parse(r.get(0)), m.deserialize(r.subList(1, r.size())));
90   }
91 
ordering(CsvKeyMarshaller<T> m)92   private static <T> Optional<Comparator<DiffKey<T>>> ordering(CsvKeyMarshaller<T> m) {
93     return m.ordering().map(o -> {
94       // Weird bug (possibly IntelliJ) means it really doesn't do well inferring types over lambdas
95       // for this sort of chained API call. Pulling into separate variables works fine.
96       Comparator<DiffKey<T>> keyFn = Comparator.comparing(DiffKey::getOriginalKey, o);
97       return keyFn.thenComparing(DiffKey::getStatus);
98     });
99   }
100 }
101