package yuku.alkitab.base.util; import yuku.alkitab.model.SongInfo; import yuku.kpri.model.Lyric; import yuku.kpri.model.Song; import yuku.kpri.model.Verse; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class SongFilter { public static final String TAG = SongFilter.class.getSimpleName(); public static class CompiledFilter { Pattern[] ps; } public static CompiledFilter compileFilter(String filter_string) { CompiledFilter res = new CompiledFilter(); if (filter_string == null || filter_string.trim().length() == 0) { res.ps = null; } else { String[] tokens = QueryTokenizer.tokenize(filter_string); Pattern[] ps = new Pattern[tokens.length]; for (int i = 0; i < tokens.length; i++) { String token = tokens[i]; if (QueryTokenizer.isPlussedToken(token)) { ps[i] = Pattern.compile("\\b" + Pattern.quote(QueryTokenizer.tokenWithoutPlus(token)) + "\\b", Pattern.CASE_INSENSITIVE); } else { ps[i] = Pattern.compile(Pattern.quote(token), Pattern.CASE_INSENSITIVE); } } res.ps = ps; } return res; } public static List<SongInfo> filterSongInfosByString(List<SongInfo> songInfos, String filter_string) { List<SongInfo> res = new ArrayList<>(); if (filter_string == null) { res.addAll(songInfos); } else { CompiledFilter cf = compileFilter(filter_string); for (SongInfo songInfo: songInfos) { if (match(songInfo, cf)) res.add(songInfo); } } return res; } public static List<Song> filterSongsByString(List<Song> songs, String filter_string) { List<Song> res = new ArrayList<>(); if (filter_string == null) { res.addAll(songs); } else { CompiledFilter cf = compileFilter(filter_string); for (Song song: songs) { if (match(song, cf)) res.add(song); } } return res; } public static boolean match(SongInfo song, CompiledFilter cf) { Pattern[] ps = cf.ps; if (ps == null) return true; // empty filter? consider it passes int matches = 0; for (final Pattern p : ps) { if (match(song, p)) matches++; } return matches == ps.length; } public static boolean match(Song song, CompiledFilter cf) { Pattern[] ps = cf.ps; if (ps == null) return true; // empty filter? consider it passes int matches = 0; for (final Pattern p : ps) { if (match(song, p)) matches++; } return matches == ps.length; } private static boolean match(SongInfo song, Pattern p) { Matcher m = p.matcher(""); if (find(song.code, m)) return true; if (find(song.title, m)) return true; if (song.title_original != null && find(song.title_original, m)) return true; return false; } private static boolean match(Song song, Pattern p) { Matcher m = p.matcher(""); if (find(song.code, m)) return true; if (find(song.title, m)) return true; if (song.title_original != null && find(song.title_original, m)) return true; if (song.authors_lyric != null) for (String author_lyric: song.authors_lyric) { if (find(author_lyric, m)) return true; } if (song.authors_music != null) for (String author_music: song.authors_music) { if (find(author_music, m)) return true; } if (song.tune != null && find(song.tune, m)) return true; for (Lyric lyric: song.lyrics) { for (Verse verse: lyric.verses) { for (String line: verse.lines) { if (find(line, m)) return true; } } } return false; } private static boolean find(CharSequence s, Matcher m) { m.reset(s); return m.find(); } }