X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=getdown%2Fsrc%2Fgetdown%2Fcore%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Futil%2FMessageUtil.java;fp=getdown%2Fsrc%2Fgetdown%2Fcore%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Futil%2FMessageUtil.java;h=28dbdcff59b4fe0756b35a603abb8b50b2e6b14c;hb=ca8504cf9d10874dce9f07cf7a9d933853fe0dd0;hp=0000000000000000000000000000000000000000;hpb=775e7bc104584e88dddcea73fbf02c66f5200c16;p=jalview.git diff --git a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/util/MessageUtil.java b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/util/MessageUtil.java new file mode 100644 index 0000000..28dbdcf --- /dev/null +++ b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/util/MessageUtil.java @@ -0,0 +1,144 @@ +// +// Getdown - application installer, patcher and launcher +// Copyright (C) 2004-2018 Getdown authors +// https://github.com/threerings/getdown/blob/master/LICENSE + +package com.threerings.getdown.util; + +public class MessageUtil { + + /** + * Returns whether or not the provided string is tainted. See {@link #taint}. Null strings + * are considered untainted. + */ + public static boolean isTainted (String text) + { + return text != null && text.startsWith(TAINT_CHAR); + } + + /** + * Call this to "taint" any string that has been entered by an entity outside the application + * so that the translation code knows not to attempt to translate this string when doing + * recursive translations. + */ + public static String taint (Object text) + { + return TAINT_CHAR + text; + } + + /** + * Removes the tainting character added to a string by {@link #taint}. If the provided string + * is not tainted, this silently returns the originally provided string. + */ + public static String untaint (String text) + { + return isTainted(text) ? text.substring(TAINT_CHAR.length()) : text; + } + + /** + * Composes a message key with an array of arguments. The message can subsequently be + * decomposed and translated without prior knowledge of how many arguments were provided. + */ + public static String compose (String key, Object... args) + { + StringBuilder buf = new StringBuilder(); + buf.append(key); + buf.append('|'); + for (int i = 0; i < args.length; i++) { + if (i > 0) { + buf.append('|'); + } + // escape the string while adding to the buffer + String arg = (args[i] == null) ? "" : String.valueOf(args[i]); + int alength = arg.length(); + for (int p = 0; p < alength; p++) { + char ch = arg.charAt(p); + if (ch == '|') { + buf.append("\\!"); + } else if (ch == '\\') { + buf.append("\\\\"); + } else { + buf.append(ch); + } + } + } + return buf.toString(); + } + + /** + * Compose a message with String args. This is just a convenience so callers do not have to + * cast their String[] to an Object[]. + */ + public static String compose (String key, String... args) + { + return compose(key, (Object[]) args); + } + + /** + * A convenience method for calling {@link #compose(String,Object[])} with an array of + * arguments that will be automatically tainted (see {@link #taint}). + */ + public static String tcompose (String key, Object... args) + { + int acount = args.length; + String[] targs = new String[acount]; + for (int ii = 0; ii < acount; ii++) { + targs[ii] = taint(args[ii]); + } + return compose(key, (Object[]) targs); + } + + /** + * A convenience method for calling {@link #compose(String,String[])} with an array of argument + * that will be automatically tainted. + */ + public static String tcompose (String key, String... args) + { + for (int ii = 0, nn = args.length; ii < nn; ii++) { + args[ii] = taint(args[ii]); + } + return compose(key, args); + } + + /** + * Used to escape single quotes so that they are not interpreted by MessageFormat. + * As we assume all single quotes are to be escaped, we cannot use the characters + * { and } in our translation strings, but this is a small price to + * pay to have to differentiate between messages that will and won't eventually be parsed by a + * MessageFormat instance. + */ + public static String escape (String message) + { + return message.replace("'", "''"); + } + + /** + * Unescapes characters that are escaped in a call to compose. + */ + public static String unescape (String value) + { + int bsidx = value.indexOf('\\'); + if (bsidx == -1) { + return value; + } + + StringBuilder buf = new StringBuilder(); + int vlength = value.length(); + for (int ii = 0; ii < vlength; ii++) { + char ch = value.charAt(ii); + if (ch != '\\' || ii == vlength-1) { + buf.append(ch); + } else { + // look at the next character + ch = value.charAt(++ii); + buf.append((ch == '!') ? '|' : ch); + } + } + + return buf.toString(); + } + + /** Text prefixed by this character will be considered tainted when doing recursive + * translations and won't be translated. */ + protected static final String TAINT_CHAR = "~"; +}