• 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 static com.google.common.base.Preconditions.checkArgument;
19 
20 import com.google.auto.value.AutoValue;
21 import com.google.common.base.Splitter;
22 import java.util.List;
23 import java.util.Optional;
24 import javax.annotation.Nullable;
25 
26 /**
27  * A single assignment of a column to a value. This can be used to change values in a
28  * {@code RangeTable} and well as query for ranges with its value.
29  */
30 @AutoValue
31 public abstract class Assignment<T extends Comparable<T>> {
32   private static final Splitter SPLITTER = Splitter.on("=").limit(2).trimResults();
33 
34   /**
35    * Parses a string of the form {@code "<column>=<value>"} to create an assignment using the given
36    * schema. The named column must exist in the schema, and the associated value must be a valid
37    * value within that column.
38    * <p>
39    * Whitespace before and after the column or value is ignored. If the value is omitted, then an
40    * unassignment is returned.
41    */
parse(String s, Schema schema)42   public static Assignment<?> parse(String s, Schema schema) {
43     List<String> parts = SPLITTER.splitToList(s);
44     checkArgument(parts.size() == 2, "invalid assigment string: %s", s);
45     Column<?> column = schema.getColumn(parts.get(0));
46     return create(column, column.parse(parts.get(1)));
47   }
48 
49   // Type capture around AutoValue is a little painful, so this static helper ... helps.
create(Column<T> c, @Nullable Object v)50   private static <T extends Comparable<T>> Assignment<T> create(Column<T> c, @Nullable Object v) {
51     T value = c.cast(v);
52     return new AutoValue_Assignment<>(c, Optional.ofNullable(value));
53   }
54 
55   /**
56    * Returns an assignment in the given column for the specified, non null, value.
57    * <p>
58    * Note that an assignment for the default value of a column will return an explicit assignment
59    * for that value, rather than an "unassignment" in that column; so
60    * {@code Assignment.of(c, c.defaultValue())} is not equal to {@code unassign(c)}, even though
61    * they may have the same effect when applied to a range table, and may even have the same
62    * {@link #toString()} representation (in the case of String columns).
63    */
of(Column<T> c, Object v)64   public static <T extends Comparable<T>> Assignment<T> of(Column<T> c, Object v) {
65     return new AutoValue_Assignment<>(c, Optional.of(c.cast(v)));
66   }
67 
68   @SuppressWarnings("unchecked")
ofOptional(Column<T> c, Optional<?> v)69   public static <T extends Comparable<T>> Assignment<T> ofOptional(Column<T> c, Optional<?> v) {
70     // Casting the value makes the optional cast below safe.
71     v.ifPresent(c::cast);
72     return new AutoValue_Assignment<>(c, (Optional<T>) v);
73   }
74 
75   /**
76    * Returns an unassignment in the given column. The {@link #value()} of this assignment is empty.
77    */
unassign(Column<T> c)78   public static <T extends Comparable<T>> Assignment<T> unassign(Column<T> c) {
79     return new AutoValue_Assignment<>(c, Optional.empty());
80   }
81 
82   /** The column in which the assignment applies. */
column()83   public abstract Column<T> column();
84 
85   /** The value in the column, or empty to signify unassignment. */
value()86   public abstract Optional<T> value();
87 
88   @Override
toString()89   public final String toString() {
90     return String.format("%s=%s", column().getName(), value().map(Object::toString).orElse(""));
91   }
92 }
93