/* * Copyright (c) 2014 Dennis Fischer. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0+ * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: Dennis Fischer */ package de.chaosfisch.services; import com.google.common.io.Files; import com.google.inject.name.Named; import de.chaosfisch.google.youtube.playlist.Playlist; import javax.inject.Inject; import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ExtendedPlaceholders { private final ResourceBundle resourceBundle; private final Pattern numberPattern; private final Pattern playlistPattern; /** * The file for the {file} placeholder */ private File file; /** * Custom user defined placeholders */ private final HashMap<String, String> map = new HashMap<>(10); /** * The playlist for the {playlist} and {number} placeholders */ private List<Playlist> playlists; /** * Creates a new instance of Extendedplaceholders * * @param file for {file} * @param playlists for {playlist(i)} and {number(i)(j)} */ public ExtendedPlaceholders(final File file, final List<Playlist> playlists, final ResourceBundle resourceBundle) { this.file = file; this.playlists = playlists; this.resourceBundle = resourceBundle; numberPattern = Pattern.compile(resourceBundle.getString("autotitle.numberPattern")); playlistPattern = Pattern.compile(resourceBundle.getString("autotitle.playlistPattern")); } @Inject public ExtendedPlaceholders(@Named("i18n-resources") final ResourceBundle resourceBundle) { this(null, null, resourceBundle); } /** * Registers a new custom placeholder * * @param placeholder the placeholder * @param replacement the replacement */ public void register(final String placeholder, final String replacement) { map.put(placeholder, replacement); } /** * Replaces all placeholders * * @param input the string to be parsed * @return the parsed string */ public String replace(String input) { if (null == input) { return ""; } if (!playlists.isEmpty()) { Matcher matcher = numberPattern.matcher(input); StringBuffer sb = new StringBuffer(input.length() + 100); while (matcher.find()) { final int playlist = getPlaylist(matcher, sb); final int number = null == matcher.group(2) ? 0 : Integer.parseInt(matcher.group(2)); final int zeros = null == matcher.group(3) ? 1 : Integer.parseInt(matcher.group(3)); if (containsPlaylist(playlist)) { sb.append(zeroFill(playlists.get(playlist).getNumber() + 1 + number, zeros)); } else { appendMissingPlaylist(sb, playlist); } } matcher.appendTail(sb); input = sb.toString(); matcher = playlistPattern.matcher(input); sb = new StringBuffer(input.length() + 100); while (matcher.find()) { final int playlist = getPlaylist(matcher, sb); if (containsPlaylist(playlist)) { sb.append(playlists.get(playlist).getTitle()); } else { appendMissingPlaylist(sb, playlist); } } matcher.appendTail(sb); input = sb.toString(); } if (null != file) { input = replaceFileTag(input, file); } for (final Map.Entry<String, String> vars : map.entrySet()) { input = input.replaceAll(Pattern.quote(vars.getKey()), vars.getValue()); } return input; } public String replaceFileTag(final String input, final File file) { final String fileName = file.getAbsolutePath(); return input.replaceAll(resourceBundle.getString("autotitle.file"), Files.getNameWithoutExtension(fileName)); } private int getPlaylist(final Matcher matcher, final StringBuffer sb) { matcher.appendReplacement(sb, ""); return null == matcher.group(1) ? 0 : Integer.parseInt(matcher.group(1)) - 1; } private void appendMissingPlaylist(final StringBuffer sb, final int playlist) { sb.append(String.format("{NO-PLAYLIST-%d}", playlist + 1)); } private boolean containsPlaylist(final int playlist) { return -1 != playlist && playlists.size() > playlist; } /** * Fills the number with X zeros * * @param number to be "filled" * @param width the number of characters * @return the filled number string */ private String zeroFill(final long number, final int width) { return String.format(String.format("%%0%dd", width), number); } /** * @return the file */ public final File getFile() { return file; } /** * @param file the file to set */ public final void setFile(final File file) { this.file = file; } /** * @return the playlists */ public final List<Playlist> getPlaylists() { return playlists; } /** * @param playlists the playlists to set */ public final void setPlaylists(final List<Playlist> playlists) { this.playlists = playlists; } }