1 /*
2  * Copyright (C) 2020 Google LLC
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.carrier;
17 
18 import static java.nio.charset.StandardCharsets.UTF_8;
19 
20 import com.beust.jcommander.JCommander;
21 import com.beust.jcommander.Parameter;
22 import com.beust.jcommander.Parameters;
23 import com.google.carrier.CarrierId;
24 import com.google.carrier.CarrierList;
25 import com.google.carrier.CarrierMap;
26 import com.google.common.base.Verify;
27 import com.google.protobuf.TextFormat;
28 import java.io.BufferedReader;
29 import java.io.BufferedWriter;
30 import java.io.IOException;
31 import java.io.OutputStream;
32 import java.nio.file.Files;
33 import java.nio.file.Paths;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.List;
37 
38 /**
39  * This command line tool generate a single carrier_list.pb. The output pb is used as a reverse-map:
40  * each entry is a CarrierMap with a canonical_name and only one CarrierId; entries are sorted by
41  * mcc_mnc, and MVNO comes before MNO. So that when matching a CarrierId against this list, the
42  * first match is always the best guess of carrier name.
43  */
44 @Parameters(separators = "=")
45 public final class GenCarrierList {
46   @Parameter(
47       names = "--version_offset",
48       description =
49           "The value to be added to file version, used to differentiate releases/branches.")
50   private long versionOffset = 0L;
51 
52   @Parameter(
53       names = "--in_textpbs",
54       description = "A comma-separated list of input CarrierList textpb files")
55   private List<String> textpbFileNames = Arrays.asList();
56 
57   @Parameter(names = "--out_pb", description = "The output CarrierList pb file")
58   private String outFileName = "/tmp/carrier_list.pb";
59 
60   @Parameter(
61       names = "--with_version_number",
62       description = "Encode version number into output pb filename.")
63   private boolean versionInFileName = false;
64 
65   public static final String BINARY_PB_SUFFIX = ".pb";
66   public static final String TEXT_PB_SUFFIX = ".textpb";
67 
main(String[] args)68   public static void main(String[] args) throws IOException {
69     GenCarrierList generator = new GenCarrierList();
70     new JCommander(generator, args);
71     generator.generate();
72   }
73 
generate()74   private void generate() throws IOException {
75     long version = 0;
76 
77     Verify.verify(
78         outFileName.endsWith(BINARY_PB_SUFFIX),
79         "Output filename must end with %s.",
80         BINARY_PB_SUFFIX);
81 
82     List<CarrierMap> list = new ArrayList<>();
83     for (String textpbFileName : textpbFileNames) {
84       // Load textpbFileName
85       CarrierList carrierList = null;
86       try (BufferedReader br = Files.newBufferedReader(Paths.get(textpbFileName), UTF_8)) {
87         CarrierList.Builder builder = CarrierList.newBuilder();
88         TextFormat.getParser().merge(br, builder);
89         carrierList = builder.build();
90       }
91 
92       // Add carrierList into list
93       for (CarrierMap cm : carrierList.getEntryList()) {
94         for (CarrierId cid : cm.getCarrierIdList()) {
95           list.add(cm.toBuilder().clearCarrierId().addCarrierId(cid).build());
96         }
97       }
98 
99       // Add up version number
100       version += carrierList.getVersion();
101     }
102 
103     // Bump version according to the release
104     version = CarrierProtoUtils.addVersionOffset(version, versionOffset);
105 
106     // Sort the list as per carrier identification algorithm requirement
107     CarrierProtoUtils.sortCarrierMapEntries(list);
108 
109     // Convert list to CarrierList
110     CarrierList clist = CarrierList.newBuilder().setVersion(version).addAllEntry(list).build();
111 
112     // Output
113     String outFileMainName = outFileName.replace(BINARY_PB_SUFFIX, "");
114     try (BufferedWriter bw =
115         Files.newBufferedWriter(Paths.get(outFileMainName + TEXT_PB_SUFFIX), UTF_8)) {
116       TextFormat.printUnicode(clist, bw);
117     }
118 
119     if (versionInFileName) {
120       outFileMainName += "-" + clist.getVersion();
121     }
122     try (OutputStream os = Files.newOutputStream(Paths.get(outFileMainName + BINARY_PB_SUFFIX))) {
123       clist.writeTo(os);
124     }
125   }
126 
GenCarrierList()127   private GenCarrierList() {}
128 }
129