blob: 202b65646b2bef85955412f9af3aa3075910fb0b [file] [log] [blame]
/*
* Copyright 2014-present Facebook, Inc.
*
* 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.buck.android.aapt;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.MoreStrings;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.FluentIterable;
import java.io.IOException;
import java.nio.file.Path;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** Represents a row from a symbols file generated by {@code aapt}. */
public class RDotTxtEntry implements Comparable<RDotTxtEntry> {
// Taken from http://developer.android.com/reference/android/R.html
public static enum RType {
ANIM,
ANIMATOR,
ARRAY,
ATTR,
BOOL,
COLOR,
DIMEN,
DRAWABLE,
FRACTION,
ID,
INTEGER,
INTERPOLATOR,
LAYOUT,
MENU,
MIPMAP,
PLURALS,
RAW,
STRING,
STYLE,
STYLEABLE,
XML;
@Override
public String toString() {
return super.toString().toLowerCase();
}
}
public static enum IdType {
INT,
INT_ARRAY;
public static IdType from(String raw) {
if (raw.equals("int")) {
return INT;
} else if (raw.equals("int[]")) {
return INT_ARRAY;
}
throw new IllegalArgumentException(String.format("'%s' is not a valid ID type.", raw));
}
@Override
public String toString() {
if (this.equals(INT)) {
return "int";
}
return "int[]";
}
}
public static final Function<String, RDotTxtEntry> TO_ENTRY =
new Function<String, RDotTxtEntry>() {
@Override
public RDotTxtEntry apply(String input) {
Optional<RDotTxtEntry> entry = parse(input);
Preconditions.checkState(entry.isPresent(), "Could not parse R.txt entry: '%s'", input);
return entry.get();
}
};
private static final Pattern TEXT_SYMBOLS_LINE = Pattern.compile("(\\S+) (\\S+) (\\S+) (.+)");
// A symbols file may look like:
//
// int id placeholder 0x7f020000
// int string debug_http_proxy_dialog_title 0x7f030004
// int string debug_http_proxy_hint 0x7f030005
// int string debug_http_proxy_summary 0x7f030003
// int string debug_http_proxy_title 0x7f030002
// int string debug_ssl_cert_check_summary 0x7f030001
// int string debug_ssl_cert_check_title 0x7f030000
//
// Note that there are four columns of information:
// - the type of the resource id (always seems to be int or int[], in practice)
// - the type of the resource
// - the name of the resource
// - the value of the resource id
public final IdType idType;
public final RType type;
public final String name;
public final String idValue;
public RDotTxtEntry(
IdType idType,
RType type,
String name,
String idValue) {
this.idType = idType;
this.type = type;
this.name = name;
this.idValue = idValue;
}
public RDotTxtEntry copyWithNewIdValue(String newIdValue) {
return new RDotTxtEntry(idType, type, name, newIdValue);
}
public static Optional<RDotTxtEntry> parse(String rDotTxtLine) {
Matcher matcher = TEXT_SYMBOLS_LINE.matcher(rDotTxtLine);
if (!matcher.matches()) {
return Optional.absent();
}
IdType idType = IdType.from(matcher.group(1));
RType type = RType.valueOf(matcher.group(2).toUpperCase());
String name = matcher.group(3);
String idValue = matcher.group(4);
return Optional.of(new RDotTxtEntry(idType, type, name, idValue));
}
public static Iterable<RDotTxtEntry> readResources(ExecutionContext context, Path rDotTxt)
throws IOException {
return FluentIterable.from(context.getProjectFilesystem().readLines(rDotTxt))
.filter(MoreStrings.NON_EMPTY)
.transform(RDotTxtEntry.TO_ENTRY);
}
/**
* A collection of Resources should be sorted such that Resources of the same type should be
* grouped together, and should be alphabetized within that group.
*/
@Override
public int compareTo(RDotTxtEntry that) {
return ComparisonChain.start()
.compare(this.type, that.type)
.compare(this.name, that.name)
.result();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof RDotTxtEntry)) {
return false;
}
RDotTxtEntry that = (RDotTxtEntry) obj;
return Objects.equal(this.type, that.type) && Objects.equal(this.name, that.name);
}
@Override
public int hashCode() {
return Objects.hashCode(type, name);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(RDotTxtEntry.class)
.add("idType", idType)
.add("type", type)
.add("name", name)
.add("idValue", idValue)
.toString();
}
}