Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions src/main/java/com/vdurmont/emoji/EmojiLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,21 @@ public static List<Emoji> loadEmojis(InputStream stream) throws IOException {
private static String inputStreamToString(
InputStream stream
) throws IOException {
StringBuilder sb = new StringBuilder();
InputStreamReader isr = new InputStreamReader(stream, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String read;
while((read = br.readLine()) != null) {
sb.append(read);
BufferedReader br = null;
try {
StringBuilder sb = new StringBuilder();
InputStreamReader isr = new InputStreamReader(stream, "UTF-8");
br = new BufferedReader(isr);
String read;
while ((read = br.readLine()) != null) {
sb.append(read);
}
return sb.toString();
} finally {
if (br != null) {
br.close();
}
}
br.close();
return sb.toString();
}

protected static Emoji buildEmojiFromJSON(
Expand All @@ -67,14 +73,8 @@ protected static Emoji buildEmojiFromJSON(
}

byte[] bytes = json.getString("emoji").getBytes("UTF-8");
String description = null;
if (json.has("description")) {
description = json.getString("description");
}
boolean supportsFitzpatrick = false;
if (json.has("supports_fitzpatrick")) {
supportsFitzpatrick = json.getBoolean("supports_fitzpatrick");
}
String description = json.optString("description", null);
boolean supportsFitzpatrick = json.optBoolean("supports_fitzpatrick", false);
List<String> aliases = jsonArrayToStringList(json.getJSONArray("aliases"));
List<String> tags = jsonArrayToStringList(json.getJSONArray("tags"));
return new Emoji(description, supportsFitzpatrick, aliases, tags, bytes);
Expand Down
64 changes: 45 additions & 19 deletions src/main/java/com/vdurmont/emoji/EmojiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,27 @@ public class EmojiManager {
static final EmojiTrie EMOJI_TRIE;

static {
InputStream stream = null;
try {
InputStream stream = EmojiLoader.class.getResourceAsStream(PATH);
stream = EmojiLoader.class.getResourceAsStream(PATH);
if (stream == null) {
throw new IllegalStateException("Emoji database not found on classpath: " + PATH);
}
List<Emoji> emojis = EmojiLoader.loadEmojis(stream);
ALL_EMOJIS = emojis;
for (Emoji emoji : emojis) {
for (String tag : emoji.getTags()) {
if (EMOJIS_BY_TAG.get(tag) == null) {
EMOJIS_BY_TAG.put(tag, new HashSet<Emoji>());
}
EMOJIS_BY_TAG.get(tag).add(emoji);
}
for (String alias : emoji.getAliases()) {
EMOJIS_BY_ALIAS.put(alias, emoji);
}
}

indexEmojis(emojis);
EMOJI_TRIE = new EmojiTrie(emojis);
Collections.sort(ALL_EMOJIS, new Comparator<Emoji>() {
public int compare(Emoji e1, Emoji e2) {
return e2.getUnicode().length() - e1.getUnicode().length();
}
});
stream.close();
sortEmojisByUnicodeLength(ALL_EMOJIS);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// Ignore cleanup failures while loading the emoji database.
}
}
}
}

Expand All @@ -59,6 +55,36 @@ public int compare(Emoji e1, Emoji e2) {
*/
private EmojiManager() {}

private static void indexEmojis(List<Emoji> emojis) {
for (Emoji emoji : emojis) {
addEmojiToTagIndex(emoji);
addEmojiToAliasIndex(emoji);
}
}

private static void addEmojiToTagIndex(Emoji emoji) {
for (String tag : emoji.getTags()) {
if (EMOJIS_BY_TAG.get(tag) == null) {
EMOJIS_BY_TAG.put(tag, new HashSet<Emoji>());
}
EMOJIS_BY_TAG.get(tag).add(emoji);
}
}

private static void addEmojiToAliasIndex(Emoji emoji) {
for (String alias : emoji.getAliases()) {
EMOJIS_BY_ALIAS.put(alias, emoji);
}
}

private static void sortEmojisByUnicodeLength(List<Emoji> emojis) {
Collections.sort(emojis, new Comparator<Emoji>() {
public int compare(Emoji e1, Emoji e2) {
return e2.getUnicode().length() - e1.getUnicode().length();
}
});
}

/**
* Returns all the {@link com.vdurmont.emoji.Emoji}s for a given tag.
*
Expand Down
132 changes: 88 additions & 44 deletions src/main/java/com/vdurmont/emoji/EmojiParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,7 @@ public static String parseToAliases(
) {
EmojiTransformer emojiTransformer = new EmojiTransformer() {
public String transform(UnicodeCandidate unicodeCandidate) {
switch (fitzpatrickAction) {
default:
case PARSE:
if (unicodeCandidate.hasFitzpatrick()) {
return ":" +
unicodeCandidate.getEmoji().getAliases().get(0) +
"|" +
unicodeCandidate.getFitzpatrickType() +
":";
}
case REMOVE:
return ":" +
unicodeCandidate.getEmoji().getAliases().get(0) +
":";
case IGNORE:
return ":" +
unicodeCandidate.getEmoji().getAliases().get(0) +
":" +
unicodeCandidate.getFitzpatrickUnicode();
}
return transformToAlias(unicodeCandidate, fitzpatrickAction);
}
};

Expand Down Expand Up @@ -231,15 +212,7 @@ public static String parseToHtmlDecimal(
) {
EmojiTransformer emojiTransformer = new EmojiTransformer() {
public String transform(UnicodeCandidate unicodeCandidate) {
switch (fitzpatrickAction) {
default:
case PARSE:
case REMOVE:
return unicodeCandidate.getEmoji().getHtmlDecimal();
case IGNORE:
return unicodeCandidate.getEmoji().getHtmlDecimal() +
unicodeCandidate.getFitzpatrickUnicode();
}
return transformToHtmlDecimal(unicodeCandidate, fitzpatrickAction);
}
};

Expand Down Expand Up @@ -286,15 +259,7 @@ public static String parseToHtmlHexadecimal(
) {
EmojiTransformer emojiTransformer = new EmojiTransformer() {
public String transform(UnicodeCandidate unicodeCandidate) {
switch (fitzpatrickAction) {
default:
case PARSE:
case REMOVE:
return unicodeCandidate.getEmoji().getHtmlHexadecimal();
case IGNORE:
return unicodeCandidate.getEmoji().getHtmlHexadecimal() +
unicodeCandidate.getFitzpatrickUnicode();
}
return transformToHtmlHexadecimal(unicodeCandidate, fitzpatrickAction);
}
};

Expand Down Expand Up @@ -421,9 +386,12 @@ public static List<String> extractEmojis(String input) {
List<String> result = new ArrayList<String>();
for (UnicodeCandidate emoji : emojis) {
if (emoji.getEmoji().supportsFitzpatrick() && emoji.hasFitzpatrick()) {
result.add(emoji.getEmoji().getUnicode(emoji.getFitzpatrick()));
result.add(emoji.getEmoji().getUnicode() +
emoji.getVariationSelectorUnicode() +
emoji.getFitzpatrickUnicode());
} else {
result.add(emoji.getEmoji().getUnicode());
result.add(emoji.getEmoji().getUnicode() +
emoji.getVariationSelectorUnicode());
}
}
return result;
Expand Down Expand Up @@ -465,11 +433,18 @@ protected static UnicodeCandidate getNextUnicodeCandidate(char[] chars, int star

if (emojiEnd != -1) {
Emoji emoji = EmojiManager.getByUnicode(new String(chars, i, emojiEnd - i));
String fitzpatrickString = (emojiEnd + 2 <= chars.length) ?
new String(chars, emojiEnd, 2) :
String variationSelector = null;
int candidateEnd = emojiEnd;
if (candidateEnd < chars.length && isVariationSelector(chars[candidateEnd])) {
variationSelector = new String(chars, candidateEnd, 1);
candidateEnd++;
}
String fitzpatrickString = (candidateEnd + 2 <= chars.length) ?
new String(chars, candidateEnd, 2) :
null;
return new UnicodeCandidate(
emoji,
variationSelector,
fitzpatrickString,
i
);
Expand Down Expand Up @@ -512,11 +487,18 @@ protected static int getEmojiEndPos(char[] text, int startPos) {

public static class UnicodeCandidate {
private final Emoji emoji;
private final String variationSelector;
private final Fitzpatrick fitzpatrick;
private final int startIndex;

private UnicodeCandidate(Emoji emoji, String fitzpatrick, int startIndex) {
private UnicodeCandidate(
Emoji emoji,
String variationSelector,
String fitzpatrick,
int startIndex
) {
this.emoji = emoji;
this.variationSelector = variationSelector;
this.fitzpatrick = Fitzpatrick.fitzpatrickFromUnicode(fitzpatrick);
this.startIndex = startIndex;
}
Expand All @@ -529,10 +511,18 @@ public boolean hasFitzpatrick() {
return getFitzpatrick() != null;
}

public boolean hasVariationSelector() {
return variationSelector != null;
}

public Fitzpatrick getFitzpatrick() {
return fitzpatrick;
}

public String getVariationSelectorUnicode() {
return hasVariationSelector() ? variationSelector : "";
}

public String getFitzpatrickType() {
return hasFitzpatrick() ? fitzpatrick.name().toLowerCase() : "";
}
Expand All @@ -550,7 +540,61 @@ public int getEmojiEndIndex() {
}

public int getFitzpatrickEndIndex() {
return getEmojiEndIndex() + (fitzpatrick != null ? 2 : 0);
return getEmojiEndIndex() +
(variationSelector != null ? variationSelector.length() : 0) +
(fitzpatrick != null ? 2 : 0);
}
}

private static String transformToAlias(
UnicodeCandidate unicodeCandidate,
FitzpatrickAction fitzpatrickAction
) {
String alias = unicodeCandidate.getEmoji().getAliases().get(0);
switch (fitzpatrickAction) {
default:
case PARSE:
if (unicodeCandidate.hasFitzpatrick()) {
return ":" + alias + "|" + unicodeCandidate.getFitzpatrickType() + ":";
}
case REMOVE:
return ":" + alias + ":";
case IGNORE:
return ":" + alias + ":" +
unicodeCandidate.getVariationSelectorUnicode() +
unicodeCandidate.getFitzpatrickUnicode();
}
}

private static String transformToHtmlDecimal(
UnicodeCandidate unicodeCandidate,
FitzpatrickAction fitzpatrickAction
) {
switch (fitzpatrickAction) {
default:
case PARSE:
case REMOVE:
return unicodeCandidate.getEmoji().getHtmlDecimal();
case IGNORE:
return unicodeCandidate.getEmoji().getHtmlDecimal() +
unicodeCandidate.getVariationSelectorUnicode() +
unicodeCandidate.getFitzpatrickUnicode();
}
}

private static String transformToHtmlHexadecimal(
UnicodeCandidate unicodeCandidate,
FitzpatrickAction fitzpatrickAction
) {
switch (fitzpatrickAction) {
default:
case PARSE:
case REMOVE:
return unicodeCandidate.getEmoji().getHtmlHexadecimal();
case IGNORE:
return unicodeCandidate.getEmoji().getHtmlHexadecimal() +
unicodeCandidate.getVariationSelectorUnicode() +
unicodeCandidate.getFitzpatrickUnicode();
}
}

Expand Down