package ru.vyarus.dropwizard.guice.module.context.debug.util; import ch.qos.logback.classic.pattern.TargetLengthBasedClassNameAbbreviator; import com.google.common.base.Joiner; import ru.vyarus.dropwizard.guice.module.installer.FeatureInstaller; import ru.vyarus.dropwizard.guice.module.installer.util.FeatureUtils; import java.util.List; /** * Helper utilities for diagnostic info rendering. Use logback's {@link TargetLengthBasedClassNameAbbreviator} * to shrink full class name to predictable size. * * @author Vyacheslav Rusakov * @since 14.07.2016 */ public final class RenderUtils { private static final TargetLengthBasedClassNameAbbreviator PACKAGE_FORMATTER = new TargetLengthBasedClassNameAbbreviator(20); private static final TargetLengthBasedClassNameAbbreviator CLASS_FORMATTER = new TargetLengthBasedClassNameAbbreviator(36); private RenderUtils() { } /** * Render installer line. Assuming installer class always ends with Installer and by removing this postfix * and converting rest to lower case we can get human readable installer name. Result may be worse for * multi-word cases, but anyway it's pretty readable. * <p> * Format: human-readable-installer-name (installer-class) *markers. * * @param type installer class * @param markers markers * @return rendered installer line */ public static String renderInstaller(final Class<FeatureInstaller> type, final List<String> markers) { return String.format("%-20s %-38s %s", FeatureUtils.getInstallerExtName(type), brackets(renderClass(type)), markers(markers)); } /** * Renders disabled installer line. The same as installer line, but with '-' before installer name and * without markers. * * @param type disabled installer class * @return rendered disabled installer line */ public static String renderDisabledInstaller(final Class<FeatureInstaller> type) { return String.format("-%-19s %-38s", FeatureUtils.getInstallerExtName(type), brackets(renderClass(type))); } /** * Renders class as: class-simple-name (class-package) *markers. * For anonymous class simple name will be Class$1. * * @param type class * @param markers markers * @return rendered class line */ public static String renderClassLine(final Class<?> type, final List<String> markers) { String name = type.getSimpleName(); if (name.isEmpty()) { // for anonymous classes name will be empty instead of e.g. SomeType$1 name = type.getName().substring(type.getName().lastIndexOf('.') + 1); } return String.format("%-28s %-26s %s", name, brackets(renderPackage(type)), markers(markers)); } /** * @param type class to render * @return class rendered in abbreviated manner (to fit it into 36 chars) * @see TargetLengthBasedClassNameAbbreviator */ public static String renderClass(final Class<?> type) { return CLASS_FORMATTER.abbreviate(type.getName()); } /** * If provided type is inner class then declaring class will be rendered instead of package. * * @param type class to render package * @return class package rendered in abbreviated manner (to fit nto 20 chars) * @see TargetLengthBasedClassNameAbbreviator */ public static String renderPackage(final Class<?> type) { return PACKAGE_FORMATTER.abbreviate(type.isMemberClass() && !type.isAnonymousClass() ? type.getDeclaringClass().getName() : type.getPackage().getName()); } /** * @param string string to apply brackets * @return provided string inside brackets */ public static String brackets(final String string) { return "(" + string + ")"; } /** * Renders markers as: *marker1,marker2.. * * @param markers markers to render (may be null) * @return rendered markers or empty string if no markers provided */ public static String markers(final List<String> markers) { String signs = ""; if (markers != null && !markers.isEmpty()) { signs = "*" + Joiner.on(", ").join(markers); } return signs; } }