/* * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package YANModPack.util.htmltmpls; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.l2jserver.gameserver.cache.HtmCache; import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; /** * @author FBIagent */ public final class HTMLTemplateParser { /** pattern to find placeholder references */ private static final Pattern _PLACEHOLDER_PATTERN = Pattern.compile("%[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*%"); public static String fromCache(String path, Map<String, HTMLTemplatePlaceholder> placeholders, HTMLTemplateFunc... funcs) { return fromCache(path, null, placeholders, funcs); } public static String fromCache(String path, L2PcInstance player, Map<String, HTMLTemplatePlaceholder> placeholders, HTMLTemplateFunc... funcs) { String string = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), path); if (string == null) return null; StringBuilder builder = new StringBuilder(string); fromStringBuilder(builder, player, placeholders, funcs); return builder.toString(); } /** * Method to process a template. The string is directly modifyed and will contain the results of the template processing. * @param string the template content * @param player the player the template is processed for * @param placeholders a map of placeholders(map has to be modifyable) * @param funcs the functions to use while processing the template */ public static void fromStringBuilder(StringBuilder string, L2PcInstance player, Map<String, HTMLTemplatePlaceholder> placeholders, HTMLTemplateFunc... funcs) { // System.out.println("fromStringBuilder(" + string + ") {"); if (string == null) return; int indexOfOffset = 0; while (indexOfOffset < string.length() - 1) { // System.out.println("-------------------------------------------"); // System.out.println("indexOfOffset=" + indexOfOffset); // find the first position of a placeholder or a custom func Matcher placeholderMatcher = _PLACEHOLDER_PATTERN.matcher(string); int nextFuncStartOffset = -1; int nextFuncEndOffset = -1; if (placeholderMatcher.find(indexOfOffset)) { nextFuncStartOffset = placeholderMatcher.start(); nextFuncEndOffset = placeholderMatcher.end(); } HTMLTemplateFunc nextFunc = null; for (HTMLTemplateFunc func : funcs) { int funcOffset = string.indexOf(func.getSequenceStart(), indexOfOffset); if (funcOffset > -1 && (nextFuncStartOffset == -1 || funcOffset < nextFuncStartOffset)) { nextFuncStartOffset = funcOffset; nextFuncEndOffset = HTMLTemplateUtils.findSequenceEnd(string, nextFuncStartOffset + func.getSequenceStart().length(), func); nextFunc = func; } } // System.out.println("nextFuncStartOffset=" + nextFuncStartOffset + "\nnextFuncEndOffset=" + nextFuncEndOffset + "\nfunc?" + (nextFunc != null)); if (nextFuncStartOffset == -1) { break; } else if (nextFunc == null) { String placeholderString = placeholderMatcher.group().substring(1, placeholderMatcher.group().length() - 1); // System.out.println("Placeholder: " + placeholderString); HTMLTemplatePlaceholder placeholder = HTMLTemplateUtils.getPlaceholder(placeholderString, placeholders); if (placeholder != null) { // System.out.println("Value: " + placeholder.getValue()); string.replace(nextFuncStartOffset, nextFuncEndOffset, placeholder.getValue()); // 2 !!! placeholder replacement can contain more placeholders and func sequences start so we set the index to search to the start of the placeholder indexOfOffset = nextFuncStartOffset; } else // skip placeholder? { // if placeholder can not be found, just remove it from the string // 1 <<< string.delete(nextFuncStartOffset, nextFuncEndOffset); // 2 !!! l2j compatible mode, we don't want to manually add things like %objectId% placeholders all the time indexOfOffset += placeholderMatcher.end() - placeholderMatcher.start(); } // placeholder replacement can contain more placeholders and func sequences start so we set the index to search to the start of the placeholder // 1 <<< indexOfOffset = nextFuncStartOffset; } else { if (nextFuncEndOffset == -1) { // this is to ignore the starting sequnces which have no ending sequence ++indexOfOffset; } else { // System.out.println("Func: " + nextFunc.getClass().getName()); StringBuilder content = new StringBuilder(string.subSequence(nextFuncStartOffset + nextFunc.getSequenceStart().length(), nextFuncEndOffset - nextFunc.getSequenceEnd().length())); // the func needs preprocessing? if (nextFunc.requiresPreprocessing()) { fromStringBuilder(content, player, placeholders, funcs); } Map<String, HTMLTemplatePlaceholder> tmpPlaceholders = nextFunc.handle(content, player, placeholders == null ? null : Collections.unmodifiableMap(placeholders), funcs); // add new entries and replace entries(temp) if (tmpPlaceholders != null) { for (HTMLTemplatePlaceholder newPlaceholder : tmpPlaceholders.values()) { if (placeholders == null) { placeholders = new HashMap<>(); } tmpPlaceholders.put(newPlaceholder.getName(), placeholders.put(newPlaceholder.getName(), newPlaceholder)); } } fromStringBuilder(content, player, placeholders, funcs); string.replace(nextFuncStartOffset, nextFuncEndOffset, content.toString()); // remove entries which were new and restore old entries if (tmpPlaceholders != null && placeholders != null) { for (Entry<String, HTMLTemplatePlaceholder> oldPlaceholder : tmpPlaceholders.entrySet()) { if (oldPlaceholder.getValue() == null) { placeholders.remove(oldPlaceholder.getKey()); } else { placeholders.put(oldPlaceholder.getKey(), oldPlaceholder.getValue()); } } } // set the current offset to the next func sequence start found, replaced content can contain more placeholders and funcs indexOfOffset = nextFuncStartOffset; } } } // System.out.println("}"); } }