LarkSheetsUtil.java
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.lark.sheets;
import com.facebook.airlift.json.JsonCodec;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Map;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.emptyToNull;
import static java.lang.Math.addExact;
import static java.lang.Math.multiplyExact;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
public final class LarkSheetsUtil
{
static final int RADIX = 26;
private static final String[] ALPHABETS = buildAlphabetTable();
private static final int MASK_REMAIN = 6;
private LarkSheetsUtil() {}
public static String loadAppSecret(String secretFile)
{
JsonCodec<Map<String, String>> codec = JsonCodec.mapJsonCodec(String.class, String.class);
final Map<String, String> content;
try {
byte[] bytes = Files.readAllBytes(Paths.get(secretFile));
content = codec.fromBytes(bytes);
}
catch (Exception e) {
throw new IllegalArgumentException("Could not read secret file " + secretFile, e);
}
String secret = content.get("app-secret");
if (emptyToNull(secret) == null) {
throw new IllegalArgumentException("app-secret not provided in " + secretFile);
}
return secret;
}
public static String mask(String str)
{
if (str != null && str.length() > MASK_REMAIN) {
char[] chars = str.toCharArray();
Arrays.fill(chars, 0, chars.length - MASK_REMAIN, '*');
return new String(chars);
}
return str;
}
public static int columnLabelToColumnIndex(String label)
{
requireNonNull(emptyToNull(label), "label is null or empty");
int length = label.length();
// Fast path
if (length == 1) {
char c = label.charAt(0);
return charToIndex(c);
}
else if (length == 2) {
char a = label.charAt(0);
char b = label.charAt(1);
return charToIndex(a) * RADIX + charToIndex(b) + RADIX;
}
// Slow path
int value = 0;
int power = 1;
int offset = -1;
for (int i = length - 1; i >= 0; i--) {
value = addExact(value, multiplyExact(charToIndex(label.charAt(i)), power));
offset = addExact(offset, power);
power = multiplyExact(power, RADIX);
}
return value + offset;
}
public static String columnIndexToColumnLabel(int index)
{
checkArgument(index >= 0, "index must be non-negative");
// Fast path
if (index < RADIX) {
// A to Z
return ALPHABETS[index];
}
else if (index < RADIX * RADIX + RADIX) {
// AA to ZZ
return ALPHABETS[index / RADIX - 1] + ALPHABETS[index % RADIX];
}
// Slow path
int power = RADIX * RADIX;
int sum = RADIX * RADIX + RADIX;
int width = 3;
int position = -1;
while (index >= sum) {
power = multiplyExact(power, RADIX);
int max = addExact(power, sum);
if (index < max) {
position = index - sum;
break;
}
sum = max;
width += 1;
}
if (position == -1) {
throw new IllegalStateException("Unexpected position value");
}
String[] chars = new String[width];
for (int i = width - 1; i >= 0; i--) {
chars[i] = ALPHABETS[position % RADIX];
position /= RADIX;
}
return String.join("", chars);
}
private static String[] buildAlphabetTable()
{
String[] table = new String[RADIX];
for (int i = 0; i < RADIX; i++) {
table[i] = Character.toString((char) ('A' + i));
}
return table;
}
private static int charToIndex(char c)
{
if (c >= 'A' && c <= 'Z') {
return c - 'A';
}
throw new IllegalArgumentException(format("Illegal char '%c' in label", c));
}
}