Example usage for com.google.common.base CaseFormat LOWER_CAMEL

List of usage examples for com.google.common.base CaseFormat LOWER_CAMEL

Introduction

In this page you can find the example usage for com.google.common.base CaseFormat LOWER_CAMEL.

Prototype

CaseFormat LOWER_CAMEL

To view the source code for com.google.common.base CaseFormat LOWER_CAMEL.

Click Source Link

Document

Java variable naming convention, e.g., "lowerCamel".

Usage

From source file:com.attribyte.relay.wp.WPSupplier.java

@Override
public void init(final Properties props, final Optional<ByteString> savedState, final Logger logger)
        throws Exception {

    if (isInit.compareAndSet(false, true)) {

        this.logger = logger;

        logger.info("Initializing WP supplier...");

        final long siteId = Long.parseLong(props.getProperty("siteId", "0"));
        if (siteId < 1L) {
            throw new Exception("A 'siteId' must be specified");
        }//from  w  w w  .jav a  2s. c o  m

        final Set<String> cachedTaxonomies = ImmutableSet.of(TAG_TAXONOMY, CATEGORY_TAXONOMY);
        final Duration taxonomyCacheTimeout = Duration.ofMinutes(30); //TODO: Configure
        final Duration userCacheTimeout = Duration.ofMinutes(30); //TODO: Configure
        initPools(props, logger);
        this.db = new DB(defaultConnectionPool, siteId, cachedTaxonomies, taxonomyCacheTimeout,
                userCacheTimeout);

        Properties siteProps = new InitUtil("site.", props, false).getProperties();
        Site overrideSite = new Site(siteProps);
        this.site = this.db.selectSite().overrideWith(overrideSite);

        logger.info(
                String.format("Initialized site %d - %s", this.site.id, Strings.nullToEmpty(this.site.title)));

        if (savedState.isPresent()) {
            startMeta = PostMeta.fromBytes(savedState.get());
        } else {
            startMeta = PostMeta.ZERO;
        }

        this.selectSleepMillis = Integer.parseInt(props.getProperty("selectSleepMillis", "30000"));

        this.selectAll = props.getProperty("selectAll", "false").equalsIgnoreCase("true");
        if (this.selectAll) {
            this.stopId = this.db.selectMaxPostId();
        } else {
            this.stopId = 0L;
        }

        String supplyIdsFileStr = props.getProperty("supplyIdsFile", "");
        if (!supplyIdsFileStr.isEmpty()) {
            this.selectAll = true;
            File supplyIdsFile = new File(supplyIdsFileStr);
            logger.info(String.format("Using 'supplyIdsFile', '%s'", supplyIdsFile.getAbsolutePath()));
            this.supplyIds = Lists.newArrayListWithExpectedSize(1024);
            List<String> lines = Files.readLines(supplyIdsFile, Charsets.UTF_8);
            for (String line : lines) {
                line = line.trim();
                if (line.isEmpty() || line.startsWith("#")) {
                    continue;
                }
                Long id = Longs.tryParse(line);
                if (id != null) {
                    this.supplyIds.add(id);
                    logger.info(String.format("Adding supplied id, '%d'", id));
                }
            }

        } else {
            this.supplyIds = null;
        }

        this.maxSelected = Integer.parseInt(props.getProperty("maxSelected", "500"));

        String allowedStatusStr = props.getProperty("allowedStatus", "").trim();
        if (!allowedStatusStr.isEmpty()) {
            if (allowedStatusStr.equalsIgnoreCase("all")) {
                this.allowedStatus = ALL_STATUS;
            } else {
                this.allowedStatus = ImmutableSet
                        .copyOf(Splitter.on(',').omitEmptyStrings().splitToList(allowedStatusStr).stream()
                                .map(Post.Status::fromString).collect(Collectors.toSet()));
            }
        } else {
            this.allowedStatus = DEFAULT_ALLOWED_STATUS;
        }

        String allowedTypesStr = props.getProperty("allowedTypes", "").trim();
        if (!allowedStatusStr.isEmpty()) {
            this.allowedTypes = ImmutableSet
                    .copyOf(Splitter.on(',').omitEmptyStrings().splitToList(allowedTypesStr)).stream()
                    .map(Post.Type::fromString).collect(Collectors.toSet());
        } else {
            this.allowedTypes = DEFAULT_ALLOWED_TYPES;
        }

        String allowedPostMetaStr = props.getProperty("allowedPostMeta", "").trim();
        if (!allowedPostMetaStr.isEmpty()) {
            this.allowedPostMeta = ImmutableSet
                    .copyOf(Splitter.on(',').omitEmptyStrings().splitToList(allowedPostMetaStr));
        } else {
            this.allowedPostMeta = ImmutableSet.of();
        }

        String allowedImageMetaStr = props.getProperty("allowedImageMeta", "").trim();
        if (!allowedImageMetaStr.isEmpty()) {
            this.allowedImageMeta = ImmutableSet
                    .copyOf(Splitter.on(',').omitEmptyStrings().splitToList(allowedImageMetaStr));
        } else {
            this.allowedImageMeta = ImmutableSet.of();
        }

        String allowedUserMetaStr = props.getProperty("allowedUserMeta", "").trim();
        if (!allowedUserMetaStr.isEmpty()) {
            this.allowedUserMeta = ImmutableSet
                    .copyOf(Splitter.on(',').omitEmptyStrings().splitToList(allowedUserMetaStr));
        } else {
            this.allowedUserMeta = ImmutableSet.of();
        }

        String metaNameCaseFormat = props.getProperty("metaNameCaseFormat", "").trim().toLowerCase();
        switch (metaNameCaseFormat) {
        case "lower_camel":
            this.metaNameCaseFormat = CaseFormat.LOWER_CAMEL;
            break;
        case "lower_hyphen":
            this.metaNameCaseFormat = CaseFormat.LOWER_HYPHEN;
            break;
        case "upper_camel":
            this.metaNameCaseFormat = CaseFormat.UPPER_CAMEL;
            break;
        case "upper_underscore":
            this.metaNameCaseFormat = CaseFormat.UPPER_UNDERSCORE;
            break;
        default:
            this.metaNameCaseFormat = null;
        }

        this.excerptOutputField = props.getProperty("excerptOutputField", "summary").toLowerCase().trim();

        this.stopOnLostMessage = props.getProperty("stopOnLostMessage", "false").equalsIgnoreCase("true");

        this.logReplicationMessage = props.getProperty("logReplicationMessage", "false")
                .equalsIgnoreCase("true");

        this.originId = props.getProperty("originId", "");

        Properties dusterProps = new InitUtil("duster.", props, false).getProperties();
        if (dusterProps.size() > 0) {
            this.httpClient = new JettyClient();
            this.httpClient.init("http.", props, logger);
            this.dusterClient = new DusterClient(dusterProps, httpClient, logger);
            logger.info("Duster is enabled...");
        } else {
            logger.info("Duster is disabled...");
        }

        if (!props.getProperty("contentTransformer", "").trim().isEmpty()) {
            this.contentTransformer = (ContentTransformer) (Class
                    .forName(props.getProperty("contentTransformer")).newInstance());
            this.contentTransformer.init(props);
        } else if (props.getProperty("cleanShortcodes", "true").equalsIgnoreCase("true")) {
            this.contentTransformer = new ShortcodeCleaner();
        }

        if (!props.getProperty("postTransformer", "").trim().isEmpty()) {
            this.postTransformer = (PostTransformer) (Class.forName(props.getProperty("postTransformer"))
                    .newInstance());
            this.postTransformer.init(props);
        } else {
            this.postTransformer = null;
        }

        if (!props.getProperty("postFilter", "").trim().isEmpty()) {
            this.postFilter = (PostFilter) (Class.forName(props.getProperty("postFilter")).newInstance());
            this.postFilter.init(props);
        } else {
            this.postFilter = null;
        }

        String dbDir = props.getProperty("metadb.dir", "").trim();
        if (dbDir.isEmpty()) {
            this.metaDB = null;
        } else {
            logger.info(String.format("Initializing meta db, '%s'...", dbDir));
            File metaDir = new File(dbDir);
            if (!metaDir.exists()) {
                throw new Exception(String.format("The 'metadb.dir' must exist ('%s')", dbDir));
            }
            this.metaDB = new PostMetaDB(metaDir);
        }

        Long modifiedOffsetHours = Longs.tryParse(props.getProperty("modifiedOffsetHours", "0"));
        this.modifiedOffsetMillis = modifiedOffsetHours != null ? modifiedOffsetHours * 3600 * 1000L : 0L;
        if (this.modifiedOffsetMillis != 0L) {
            logger.info(String.format("Set modified select offset to %d millis", this.modifiedOffsetMillis));
        }

        this.replicateScheduledState = props.getProperty("replicateScheduledState", "true")
                .equalsIgnoreCase("true");
        this.replicatePendingState = props.getProperty("replicatePendingState", "false")
                .equalsIgnoreCase("true");

        logger.info("Initialized WP supplier...");

    }
}

From source file:com.cinchapi.concourse.shell.ConcourseShell.java

/**
 * Attempt to return the {@link #ACCESSIBLE_API_METHODS API method} that is
 * the closest match for the specified {@code alias}.
 * <p>/*from  w  w w. j  a va2s . c  om*/
 * This method can be used to take a user supplied method name that does not
 * match any of the {@link #ACCESSIBLE_API_METHODS provided} ones, but can
 * be reasonably assumed to be a valid alias of some sort (i.e. an API
 * method name in underscore case as opposed to camel case).
 * </p>
 * 
 * @param alias the method name that may be an alias for one of the provided
 *            API methods
 * @return the actual API method that {@code alias} should resolve to, if it
 *         is possible to determine that; otherwise {@code null}
 */
@Nullable
private static String tryGetCorrectApiMethod(String alias) {
    String camel = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, alias);
    String expanded = com.cinchapi.concourse.util.Strings.ensureStartsWith(camel, "concourse.");
    return methods.contains(expanded) && !camel.equals(alias) ? camel : null;
}

From source file:dagger2.internal.codegen.SourceFiles.java

private static String factoryPrefix(ProvisionBinding binding) {
    switch (binding.bindingKind()) {
    case INJECTION:
        return "";
    case PROVISION:
        return CaseFormat.LOWER_CAMEL.to(UPPER_CAMEL,
                ((ExecutableElement) binding.bindingElement()).getSimpleName().toString());
    default:/*from w ww  .j a  v a 2 s.  co  m*/
        throw new IllegalArgumentException();
    }
}

From source file:com.google.template.soy.shared.internal.AbstractGenerateSoyEscapingDirectiveCode.java

/**
 * Appends Code to the given buffer./*from   w  w w .  j  a v a  2 s. c o  m*/
 *
 * <p>
 * The output Code contains symbol definitions in the appropriate scope (the soy namespace in
 * JavaScript or a module in Python).
 * <pre>
 *   ...ESCAPES_FOR_ESCAPE_HTML_  = { ... }  // Maps of characters to escaped versions
 *   ...MATCHER_FOR_ESCAPE_HTML_  = &lt;regex&gt;  // A single character matching RegExp
 *   ...REPLACER_FOR_ESCAPE_HTML_ = &lt;function&gt;  // Usable with replace functions
 *   ...FILTER_FOR_ESCAPE_HTML_ = &lt;regex&gt;  // Optional regular expression that vets values.
 *   // A function that uses the above definitions.
 *   ...escapeHtmlHelper = &lt;function&gt;
 * </pre>
 *
 * <p>There is not necessarily a one-to-one relationship between any of the symbols above
 * and escape directives except for the {@code ...escape...Helper} function.
 *
 * @param availableIdentifiers Determines whether a qualified identifier, like
 *     {@code goog.foo.Bar}, is available.
 * @param outputCode Receives output code.
 */
@VisibleForTesting
void generateCode(Predicate<String> availableIdentifiers, StringBuilder outputCode) {

    outputCode.append(GENERATED_CODE_START_MARKER).append('\n');

    // Before entering the real logic, generate any needed prefix.
    generatePrefix(outputCode);

    // First we collect all the side tables.

    // Like { '\n': '\\n', ... } that map characters to escape.
    List<Map<Character, String>> escapeMaps = Lists.newArrayList();
    // Mangled directive names corresponding to escapeMaps used to generate <namespace>..._ names.
    List<String> escapeMapNames = Lists.newArrayList();
    // Like /[\n\r'"]/g or r'[\n\r\'"]'that match all the characters that need escaping.
    List<String> matchers = Lists.newArrayList();
    // Mangled directive names corresponding to matchers.
    List<String> matcherNames = Lists.newArrayList();
    // RegExps that vet input values.
    List<String> filters = Lists.newArrayList();
    // Mangled directive names corresponding to filters.
    List<String> filterNames = Lists.newArrayList();
    // Bundles of directiveNames and indices into escapeMaps, matchers, etc.
    List<DirectiveDigest> digests = Lists.newArrayList();

    escaperLoop: for (EscapingConventions.CrossLanguageStringXform escaper : EscapingConventions
            .getAllEscapers()) {
        // "|escapeHtml" -> "escapeHtml"
        String escapeDirectiveIdent = escaper.getDirectiveName().substring(1);
        // "escapeHtml" -> "ESCAPE_HTML"
        String escapeDirectiveUIdent = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
                escapeDirectiveIdent);

        // If there is an existing function, use it.
        for (String existingFunction : escaper.getLangFunctionNames(getLanguage())) {
            if (availableIdentifiers.apply(existingFunction)) {
                useExistingLibraryFunction(outputCode, escapeDirectiveIdent, existingFunction);
                continue escaperLoop;
            }
        }

        // Else generate definitions for side tables.
        int escapesVar = -1;
        int matcherVar = -1;
        if (!escaper.getEscapes().isEmpty()) {
            Map<Character, String> escapeMap = Maps.newTreeMap();
            StringBuilder matcherRegexBuf = new StringBuilder(getRegexStart() + "[");
            int lastCodeUnit = Integer.MIN_VALUE;
            int rangeStart = Integer.MIN_VALUE;
            for (EscapingConventions.Escape esc : escaper.getEscapes()) {
                char ch = esc.getPlainText();
                if (ch == lastCodeUnit) {
                    throw new IllegalStateException(
                            "Ambiguous escape " + esc.getEscaped() + " for " + escapeDirectiveIdent);
                }
                escapeMap.put(ch, esc.getEscaped());
                if (ch != lastCodeUnit + 1) {
                    if (rangeStart != Integer.MIN_VALUE) {
                        escapeRegexpRangeOnto((char) rangeStart, (char) lastCodeUnit, matcherRegexBuf);
                    }
                    rangeStart = ch;
                }
                lastCodeUnit = ch;
            }
            if (rangeStart < 0) {
                throw new IllegalStateException();
            }
            escapeRegexpRangeOnto((char) rangeStart, (char) lastCodeUnit, matcherRegexBuf);
            matcherRegexBuf.append("]").append(getRegexEnd());

            // See if we can reuse an existing map.
            int numEscapeMaps = escapeMaps.size();
            for (int i = 0; i < numEscapeMaps; ++i) {
                if (mapsHaveCompatibleOverlap(escapeMaps.get(i), escapeMap)) {
                    escapesVar = i;
                    break;
                }
            }
            if (escapesVar == -1) {
                escapesVar = numEscapeMaps;
                escapeMaps.add(escapeMap);
                escapeMapNames.add(escapeDirectiveUIdent);
            } else {
                escapeMaps.get(escapesVar).putAll(escapeMap);
                // ESCAPE_JS -> ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX
                escapeMapNames.set(escapesVar,
                        escapeMapNames.get(escapesVar) + "__AND__" + escapeDirectiveUIdent);
            }

            String matcherRegex = matcherRegexBuf.toString();
            matcherVar = matchers.indexOf(matcherRegex);
            if (matcherVar < 0) {
                matcherVar = matchers.size();
                matchers.add(matcherRegex);
                matcherNames.add(escapeDirectiveUIdent);
            } else {
                matcherNames.set(matcherVar, matcherNames.get(matcherVar) + "__AND__" + escapeDirectiveUIdent);
            }
        }

        // Find a suitable filter or add one to filters.
        int filterVar = -1;
        Pattern filterPatternJava = escaper.getValueFilter();
        if (filterPatternJava != null) {
            // This is an approximate translation from Java patterns to JavaScript patterns.
            String filterPattern = convertFromJavaRegex(filterPatternJava);
            filterVar = filters.indexOf(filterPattern);
            if (filterVar == -1) {
                filterVar = filters.size();
                filters.add(filterPattern);
                filterNames.add(escapeDirectiveUIdent);
            } else {
                filterNames.set(filterVar, filterNames.get(filterVar) + "__AND__" + escapeDirectiveUIdent);
            }
        }

        digests.add(new DirectiveDigest(escapeDirectiveIdent, escapesVar, matcherVar, filterVar,
                escaper.getNonAsciiPrefix(), escaper.getInnocuousOutput()));
    }

    // TODO(user): Maybe use java Soy templates to generate the JS?

    // Output the tables.
    for (int i = 0; i < escapeMaps.size(); ++i) {
        Map<Character, String> escapeMap = escapeMaps.get(i);
        String escapeMapName = escapeMapNames.get(i);
        generateCharacterMapSignature(outputCode, escapeMapName);
        outputCode.append(" = {");
        boolean needsComma = false;
        for (Map.Entry<Character, String> e : escapeMap.entrySet()) {
            if (needsComma) {
                outputCode.append(',');
            }
            outputCode.append("\n  ");
            writeUnsafeStringLiteral(e.getKey(), outputCode);
            outputCode.append(": ");
            writeStringLiteral(e.getValue(), outputCode);
            needsComma = true;
        }
        outputCode.append("\n}").append(getLineEndSyntax()).append("\n");

        generateReplacerFunction(outputCode, escapeMapName);
    }

    for (int i = 0; i < matchers.size(); ++i) {
        String matcherName = matcherNames.get(i);
        String matcher = matchers.get(i);
        generateMatcher(outputCode, matcherName, matcher);
    }

    for (int i = 0; i < filters.size(); ++i) {
        String filterName = filterNames.get(i);
        String filter = filters.get(i);
        generateFilter(outputCode, filterName, filter);
    }

    // Finally, define the helper functions that use the escapes, filters, matchers, etc.
    for (DirectiveDigest digest : digests) {
        digest.updateNames(escapeMapNames, matcherNames, filterNames);
        generateHelperFunction(outputCode, digest);
    }

    // Emit patterns and constants needed by escaping functions that are not part of any one
    // escaping convention.
    generateCommonConstants(outputCode);

    outputCode.append('\n').append(GENERATED_CODE_END_MARKER).append('\n');
}

From source file:dagger.internal.codegen.MembersInjectorGenerator.java

private static String injectionSiteDelegateMethodName(Element injectionSiteElement) {
    return "inject" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL,
            injectionSiteElement.getSimpleName().toString());
}

From source file:dagger2.internal.codegen.SourceFiles.java

private static String factoryPrefix(ProductionBinding binding) {
    switch (binding.bindingKind()) {
    case IMMEDIATE:
    case FUTURE_PRODUCTION:
        return CaseFormat.LOWER_CAMEL.to(UPPER_CAMEL,
                ((ExecutableElement) binding.bindingElement()).getSimpleName().toString());
    default:/*from w  w  w.  j a  va2s  .c o m*/
        throw new IllegalArgumentException();
    }
}

From source file:brooklyn.util.flags.TypeCoercions.java

/**
 * Type coercion {@link Function function} for {@link Enum enums}.
 * <p>/*from ww  w  .  j  a v a  2 s .co m*/
 * Tries to convert the string to {@link CaseFormat#UPPER_UNDERSCORE} first,
 * handling all of the different {@link CaseFormat format} possibilites. Failing 
 * that, it tries a case-insensitive comparison with the valid enum values.
 * <p>
 * Returns {@code defaultValue} if the string cannot be converted.
 *
 * @see TypeCoercions#coerce(Object, Class)
 * @see Enum#valueOf(Class, String)
 */
public static <E extends Enum<E>> Function<String, E> stringToEnum(final Class<E> type,
        @Nullable final E defaultValue) {
    return new Function<String, E>() {
        @Override
        public E apply(String input) {
            Preconditions.checkNotNull(input, "input");
            List<String> options = ImmutableList.of(input,
                    CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, input),
                    CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, input),
                    CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input),
                    CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input));
            for (String value : options) {
                try {
                    return Enum.valueOf(type, value);
                } catch (IllegalArgumentException iae) {
                    continue;
                }
            }
            Maybe<E> result = Enums.valueOfIgnoreCase(type, input);
            return (result.isPresent()) ? result.get() : defaultValue;
        }
    };
}

From source file:org.immutables.value.processor.meta.ValueType.java

public String getDocumentName() {
    Optional<RepositoryMirror> repositoryAnnotation = RepositoryMirror.find(element);
    if (repositoryAnnotation.isPresent()) {
        String value = repositoryAnnotation.get().value();
        if (!value.isEmpty()) {
            return value;
        }// www.j ava 2  s .  c o  m
    }
    return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, name());
}

From source file:org.jclouds.virtualbox.functions.MastersLoadingCache.java

private String getOsTypeId(String os_family, boolean os_64bit) {
    String osFamily = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, os_family);
    return os_64bit ? osFamily + "_64" : osFamily;
}

From source file:com.google.template.soy.jssrc.internal.GenerateSoyUtilsEscapingDirectiveCode.java

/**
 * Appends JavaScript to the given buffer.
 *
 * <p>//from www. j  a  v a2s  .  c om
 * The output JavaScript contains symbol definitions in the soy namespace.
 * <pre>
 *   soy.esc.$$ESCAPES_FOR_ESCAPE_HTML_  = { ... };  // Maps of characters to escaped versions
 *   soy.esc.$$MATCHER_FOR_ESCAPE_HTML_  = /.../g;  // A single character matching RegExp
 *   soy.esc.$$REPLACER_FOR_ESCAPE_HTML_ = function(ch) { ... };  // Usable with String.replace
 *   soy.esc.$$FILTER_FOR_ESCAPE_HTML_ = /.../g;  // Optional regular expression that vets values.
 *   // A function that uses the above definitions.
 *   soy.esc.$$escapeHtmlHelper = function(value) { return ...; };
 * </pre>
 * These definitions are all marked {@code @private} and have Closure compiler type
 * annotations.
 *
 * <p>There is not necessarily a one-to-one relationship between any of the symbols above
 * and escape directives except for the {@code soy.esc.$$escape...Helper} function.
 *
 * @param availableJavaScript Determines whether a qualified JavaScript identifier, like
 *     {@code goog.foo.Bar}, is available.
 * @param outputJs Receives output JavaScript.
 */
@VisibleForTesting
void generateJavaScript(Predicate<String> availableJavaScript, StringBuilder outputJs) {

    /**
     * The JS identifiers associated with the support for a particular escaping directive.
     */
    class DirectiveDigest {
        /** The name of the directive to output. */
        final String directiveName;

        /** Index into escapes of the object that maps characters to escaped text. */
        final int escapesVar;

        /** Index into matchers. */
        final int matcherVar;

        /** Index into filters. */
        final int filterVar;

        /** The prefix to use for non-ASCII characters not in the escape map. */
        final @Nullable String nonAsciiPrefix;

        /** Innocuous output for this context. */
        final String innocuousOutput;

        DirectiveDigest(String directiveName, int escapesVar, int matcherVar, int filterVar,
                @Nullable String nonAsciiPrefix, String innocuousOutput) {
            this.directiveName = directiveName;
            this.escapesVar = escapesVar;
            this.matcherVar = matcherVar;
            this.filterVar = filterVar;
            this.nonAsciiPrefix = nonAsciiPrefix;
            this.innocuousOutput = innocuousOutput;
        }
    }

    outputJs.append('\n').append(GENERATED_CODE_START_MARKER).append('\n');

    // First we collect all the side tables.

    // Like { '\n': '\\n', ... } that map characters to escape.
    List<Map<Character, String>> escapeMaps = Lists.newArrayList();
    // Mangled directive names corresponding to escapeMaps used to generate soy.esc.$$..._ names.
    List<String> escapeMapNames = Lists.newArrayList();
    // Like /[\n\r'"]/g that match all the characters that need escaping.
    List<String> matchers = Lists.newArrayList();
    // Mangled directive names corresponding to matchers.
    List<String> matcherNames = Lists.newArrayList();
    // RegExps that vet input values.
    List<String> filters = Lists.newArrayList();
    // Mangled directive names corresponding to filters.
    List<String> filterNames = Lists.newArrayList();
    // Bundles of directiveNames and indices into escapeMaps, matchers, etc.
    List<DirectiveDigest> digests = Lists.newArrayList();

    escaperLoop: for (EscapingConventions.CrossLanguageStringXform escaper : EscapingConventions
            .getAllEscapers()) {
        // "|escapeHtml" -> "escapeHtml"
        String escapeDirectiveIdent = escaper.getDirectiveName().substring(1);
        // "escapeHtml" -> "ESCAPE_HTML"
        String escapeDirectiveUIdent = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE,
                escapeDirectiveIdent);

        // If there is an existing function, use it.
        for (String existingFunction : escaper.getJsFunctionNames()) {
            if (availableJavaScript.apply(existingFunction)) {
                // soy.esc.$$escapeFooHelper = bar;
                outputJs.append('\n').append("/**\n").append(" * @type {function (*) : string}\n")
                        .append(" */\n").append("soy.esc.$$").append(escapeDirectiveIdent)
                        .append("Helper = function(v) {\n").append("  return ").append(existingFunction)
                        .append("(String(v));\n").append("};\n");
                continue escaperLoop;
            }
        }

        // Else generate definitions for side tables.
        int escapesVar = -1;
        int matcherVar = -1;
        if (!escaper.getEscapes().isEmpty()) {
            Map<Character, String> escapeMap = Maps.newLinkedHashMap();
            StringBuilder matcherRegexBuf = new StringBuilder("/[");
            int lastCodeUnit = Integer.MIN_VALUE;
            int rangeStart = Integer.MIN_VALUE;
            for (EscapingConventions.Escape esc : escaper.getEscapes()) {
                char ch = esc.getPlainText();
                if (ch == lastCodeUnit) {
                    throw new IllegalStateException(
                            "Ambiguous escape " + esc.getEscaped() + " for " + escapeDirectiveIdent);
                }
                escapeMap.put(ch, esc.getEscaped());
                if (ch != lastCodeUnit + 1) {
                    if (rangeStart != Integer.MIN_VALUE) {
                        escapeRegexpRangeOnto((char) rangeStart, (char) lastCodeUnit, matcherRegexBuf);
                    }
                    rangeStart = ch;
                }
                lastCodeUnit = ch;
            }
            if (rangeStart < 0) {
                throw new IllegalStateException();
            }
            escapeRegexpRangeOnto((char) rangeStart, (char) lastCodeUnit, matcherRegexBuf);
            matcherRegexBuf.append("]/g");

            // See if we can reuse an existing map.
            int numEscapeMaps = escapeMaps.size();
            for (int i = 0; i < numEscapeMaps; ++i) {
                if (mapsHaveCompatibleOverlap(escapeMaps.get(i), escapeMap)) {
                    escapesVar = i;
                    break;
                }
            }
            if (escapesVar == -1) {
                escapesVar = numEscapeMaps;
                escapeMaps.add(escapeMap);
                escapeMapNames.add(escapeDirectiveUIdent);
            } else {
                escapeMaps.get(escapesVar).putAll(escapeMap);
                // ESCAPE_JS -> ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX
                escapeMapNames.set(escapesVar,
                        escapeMapNames.get(escapesVar) + "__AND__" + escapeDirectiveUIdent);
            }

            String matcherRegex = matcherRegexBuf.toString();
            matcherVar = matchers.indexOf(matcherRegex);
            if (matcherVar < 0) {
                matcherVar = matchers.size();
                matchers.add(matcherRegex);
                matcherNames.add(escapeDirectiveUIdent);
            } else {
                matcherNames.set(matcherVar, matcherNames.get(matcherVar) + "__AND__" + escapeDirectiveUIdent);
            }
        }

        // Find a suitable filter or add one to filters.
        int filterVar = -1;
        Pattern filterPatternJava = escaper.getValueFilter();
        if (filterPatternJava != null) {
            // This is an approximate translation from Java patterns to JavaScript patterns.
            String filterPattern = javaRegexToJs(filterPatternJava);
            filterVar = filters.indexOf(filterPattern);
            if (filterVar == -1) {
                filterVar = filters.size();
                filters.add(filterPattern);
                filterNames.add(escapeDirectiveUIdent);
            } else {
                filterNames.set(filterVar, filterNames.get(filterVar) + "__AND__" + escapeDirectiveUIdent);
            }
        }

        digests.add(new DirectiveDigest(escapeDirectiveIdent, escapesVar, matcherVar, filterVar,
                escaper.getNonAsciiPrefix(), escaper.getInnocuousOutput()));
    }

    // TODO: Maybe use java Soy templates to generate the JS?

    // Output the tables.
    for (int i = 0; i < escapeMaps.size(); ++i) {
        Map<Character, String> escapeMap = escapeMaps.get(i);
        String escapeMapName = escapeMapNames.get(i);
        outputJs.append('\n').append("/**\n")
                .append(" * Maps charcters to the escaped versions for the named escape directives.\n")
                .append(" * @type {Object.<string, string>}\n").append(" * @private\n").append(" */\n")
                .append("soy.esc.$$ESCAPE_MAP_FOR_").append(escapeMapName).append("_ = {");
        boolean needsComma = false;
        for (Map.Entry<Character, String> e : escapeMap.entrySet()) {
            if (needsComma) {
                outputJs.append(',');
            }
            outputJs.append("\n  ");
            writeJsChar(e.getKey(), outputJs);
            outputJs.append(": ");
            writeJsString(e.getValue(), outputJs);
            needsComma = true;
        }
        outputJs.append("\n};\n");

        outputJs.append('\n').append("/**\n").append(" * A function that can be used with String.replace..\n")
                .append(" * @param {string} ch A single character matched by a compatible matcher.\n")
                .append(" * @return {string} A token in the output language.\n").append(" * @private\n")
                .append(" */\n").append("soy.esc.$$REPLACER_FOR_").append(escapeMapName)
                .append("_ = function(ch) {\n").append("  return soy.esc.$$ESCAPE_MAP_FOR_")
                .append(escapeMapName).append("_[ch];\n").append("};\n");
    }

    for (int i = 0; i < matchers.size(); ++i) {
        String matcher = matchers.get(i);
        String matcherName = matcherNames.get(i);
        outputJs.append('\n').append("/**\n")
                .append(" * Matches characters that need to be escaped for the named directives.\n")
                .append(" * @type RegExp\n").append(" * @private\n").append(" */\n")
                .append("soy.esc.$$MATCHER_FOR_").append(matcherName).append("_ = ").append(matcher)
                .append(";\n");
    }

    for (int i = 0; i < filters.size(); ++i) {
        String filter = filters.get(i);
        String filterName = filterNames.get(i);
        outputJs.append('\n').append("/**\n")
                .append(" * A pattern that vets values produced by the named directives.\n")
                .append(" * @type RegExp\n").append(" * @private\n").append(" */\n")
                .append("soy.esc.$$FILTER_FOR_").append(filterName).append("_ = ").append(filter).append(";\n");
    }

    // Finally, define the helper functions that use the escapes, filters, matchers, etc.
    for (DirectiveDigest digest : digests) {
        String name = digest.directiveName;
        outputJs.append('\n').append("/**\n").append(" * A helper for the Soy directive |").append(name)
                .append('\n')
                .append(" * @param {*} value Can be of any type but will be coerced to a string.\n")
                .append(" * @return {string} The escaped text.\n").append(" */\n").append("soy.esc.$$")
                .append(name).append("Helper = function(value) {\n").append("  var str = String(value);\n");
        if (digest.filterVar != -1) {
            String filterName = filterNames.get(digest.filterVar);
            outputJs.append("  if (!soy.esc.$$FILTER_FOR_").append(filterName).append("_.test(str)) {\n");
            if (availableJavaScript.apply("goog.asserts.fail")) {
                outputJs.append("    goog.asserts.fail('Bad value `%s` for |").append(name)
                        .append("', [str]);\n");
            }
            outputJs.append("    return '").append(digest.innocuousOutput).append("';\n").append("  }\n");
        }

        if (digest.nonAsciiPrefix != null) {
            // TODO: We can add a second replace of all non-ascii codepoints below.
            throw new UnsupportedOperationException("Non ASCII prefix escapers not implemented yet.");
        }
        if (digest.escapesVar >= 0) {
            String escapeMapName = escapeMapNames.get(digest.escapesVar);
            String matcherName = matcherNames.get(digest.matcherVar);
            outputJs.append("  return str.replace(\n").append("      soy.esc.$$MATCHER_FOR_")
                    .append(matcherName).append("_,\n").append("      soy.esc.$$REPLACER_FOR_")
                    .append(escapeMapName).append("_);\n");
        } else {
            outputJs.append("  return str;\n");
        }
        outputJs.append("};\n");
    }

    // Emit patterns and constants needed by escaping functions that are not part of any one
    // escaping convention.
    outputJs.append('\n').append("/**\n")
            .append(" * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML.\n")
            .append(" * By removing these, and replacing any '<' or '>' characters with\n")
            .append(" * entities we guarantee that the result can be embedded into a\n")
            .append(" * an attribute without introducing a tag boundary.\n").append(" *\n")
            .append(" * @type {RegExp}\n").append(" * @private\n").append(" */\n")
            .append("soy.esc.$$HTML_TAG_REGEX_ = ").append(javaRegexToJs(EscapingConventions.HTML_TAG_CONTENT))
            .append("g;\n").append("\n").append("/**\n").append(" * Matches all occurrences of '<'.\n")
            .append(" *\n").append(" * @type {RegExp}\n").append(" * @private\n").append(" */\n")
            .append("soy.esc.$$LT_REGEX_ = /</g;\n");

    outputJs.append('\n').append("/**\n").append(" * Maps lower-case names of innocuous tags to 1.\n")
            .append(" *\n").append(" * @type {Object.<string,number>}\n").append(" * @private\n")
            .append(" */\n").append("soy.esc.$$SAFE_TAG_WHITELIST_ = ")
            .append(toJsStringSet(TagWhitelist.FORMATTING.asSet())).append(";\n");

    outputJs.append('\n').append(GENERATED_CODE_END_MARKER).append('\n');
}