All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nerd4j.utils.lang.ToString Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * Nerd4j Core
 * %%
 * Copyright (C) 2011 - 2013 Nerd4j
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nerd4j.utils.lang;

import java.util.LinkedList;
import java.util.List;


/**
 * This utility class is intended to be used inside the method {@link #toString()} of a class.
 *
 * 

* The aim of this class, is to avoid the boilerplate code needed to implement * the {@link #toString()} method. * *

* Even if most of the IDEs provide tools to generate implementations of {@link #toString()}, * the generated code is ugly and hard to understand. * By using this utility class the resulting {@link #toString()} method will be small, * clean and easy to read. * *

* You may have seen a lot of times implementation of the method {@link #toString()} * in this form: *

 * public String toString()
 * {
 *
 *   return "SomeType{" +
 *     id=" + id +
 *     ", string='" + string + '\'' +
 *     ", intArray=" + Arrays.toString(intArray) +
 *     ", stringMatrix=" + Arrays.toString(stringMatrix) +
 *     '}';
 *
 * }
 * 
* * With this utility you can get the same result with some more concise * and elegant code: *
 *  public String toString()
 *  {
 *    return ToString.of( this )
 *      .print( "id", id )
 *      .print( "string", string )
 *      .print( "intArray", intArray )
 *      .print( "stringMatrix", stringMatrix )
 *      .likeIntellij();
 *  }
 * 
* *

* In addition, to change your objects layout the only one thing * you need to do is to change the last method of the functional * invocation chain. * * @author Massimo Coluzzi * @since 2.0.0 */ public class ToString { /** * This class is intended to be static * so there is no public constructor. */ ToString() {} /* **************** */ /* PUBLIC METHODS */ /* **************** */ /** * Returns an instance of {@link ToString.Configurator} * in order to instruct the {@link ToString} facility * on how to build the text representation of the * given object. * * @param object an object to be converted to {@link String}. * @return an instance of the {@link ToString.Configurator}. */ public static Configurator of( Object object ) { return new Config( object ); } /* *************** */ /* INNER CLASSES */ /* *************** */ /** * Represents a printer able to build the {@link String} * representation of an object using the given * {@link ToString.Configuration}. * * @author Massimo Coluzzi * @since 2.0.0 */ public interface Printer { /** * Applies the given {@link ToString.Configuration} * to create the {@link String} representation of * an object. * * @param configuration the {@link ToString.Configuration} to be applied. * @return the {@link String} representation an object. */ String apply( Configuration configuration ); } /** * Contains the information needed by the {@link ToString.Printer} * to know how to build the {@link String} representation of an object. * * @author Massimo Coluzzi * @since 2.0.0 */ public interface Configuration { /** * Returns the object of which to build * the {@link String} representation. * * @return the target object to print. */ Object target(); /** * List of fields to be printed. * * @return the list of fields to be printed. */ Iterable fields(); /** * Tells to the {@link ToString.Printer} * to use the fully qualified class name. * * @return {@code true} if the class name * should be fully qualified. */ boolean fullClassPath(); /** * Custom text to use instead of the target class name. * This can be useful when the target is an instance of * an anonymous class (like a lambda expression). * * @return custom text to use instead of the target class name. */ String customClassName(); /* *************** */ /* INNER CLASSES */ /* *************** */ /** * Represents a field to be displayed * in the resulting {@link String}. * *

* Both the {@link Field#name} and * the {@link Field#value} * can be {@code null}. * * @author Massimo Coluzzi * @since 2.0.0 */ class Field { /** The name of the field. */ public final String name; /** The value of the field. */ public final Object value; /** * Constructor with parameters. * * @param name name of the field. * @param value value of the field. */ public Field( String name, Object value ) { super(); this.name = name; this.value = value; } } } /** * Implementation of the {@code Pattern Builder} with the * purpose to properly create a {@link ToString.Configuration}. * * @author Massimo Coluzzi * @since 2.0.0 */ public interface Configurator { /** * Adds the given list of values as unnamed * {@link Configuration.Field Fields} in the * resulting {@link Configuration}. * * @param values values to add to the configuration. * @return this {@link Configurator}. */ Configurator print( Object... values ); /** * Adds the given {@code } pair * as a named {@link Configuration.Field Field} * in the resulting {@link Configuration}. * * @param name the name of the field. * @param value the value of the field. * @return this {@link Configurator}. */ Configurator print( String name, Object value ); /** * Tells the {@link ToString} class to do not print * the class name in any form. * * @return this {@link Configurator}. */ Configurator withNoClassName(); /** * Tells the {@link ToString} class to print * the full qualified class name. * * @return this {@link Configurator}. */ Configurator withFullClassName(); /** * Tells the {@link ToString} class to print * the given text instead of the class name. *

* If you invoke this method with {@code null} * than {@code "null"} will be printed instead * of the class name. * * @param value value of the custom text to set. * @return this {@link Configurator}. */ Configurator withCustomClassName( String value ); /** * Creates the {@link Configuration} and invokes * the provided {@link Printer} in order to * build the requested {@link String} representation. *

* This method provides the widest range of customizations. * You can implement is own favorite style to display objects. * * @param printer the printer to invoke. * @return the requested {@link String} representation. */ String like( Printer printer ); /** * Creates an output of the method {@link #toString()} * like the one generated by the {@code Eclipse IDE}. * * @return an output like the one generated by the {@code Eclipse IDE}. */ String likeEclipse(); /** * Creates an output of the method {@link #toString()} * like the one generated by the {@code IntelliJ IDE}. * * @return an output like the one generated by the {@code IntelliJ IDE}. */ String likeIntellij(); /** * Creates an output of the method {@link #toString()} * in the form of a function, where the function name is the * target class name and the given fields are listed as the * function arguments. *

* This method is intended to be used to implement the * {@link #toString()} method of functional classes. *

* For example if you are developing a class to apply some * operations dynamically, you may want the {@link #toString()} * of your class to be something like: {@code Apply(MyOperation)} * or {@code Apply(op:MyOperation)} * * @return an output similar to a function. */ String likeFunction(); /** * Creates an output of the method {@link #toString()} * in the form of a tuple, optionally preceded by the * class name. *

* This method is intended to be used to implement the * {@link #toString()} method of classes that represents * relations or ordered collections of objects. *

* For example if you develop a class that represents * a pair of objects, you may want the {@link #toString()} * of you class to be something like: {@code }. * * @return an output similar to a tuple. */ String likeTuple(); /** * Creates an output of the method {@link #toString()} * using the given prefix and suffix and using the given * separators. *

* The resulting string will have the following components: *

    *
  1. Optionally: the name of the class or a custom text.
  2. *
  3. The given prefix.
  4. *
  5. * A list of fields separated by the given field separators * where each field can be: *
      *
    • a value or
    • *
    • a name-value pair separated by the given name-value separator
    • *
    *
  6. *
  7. The given suffix.
  8. *
* All parameters are optional and can be {@code null} or empty. *

* This method provides a quite wide range of customizations. * If you need to customize your {@link #toString()} output even more * you can use the method {@link #like(ToString.Printer)}. * * @param prefix the prefix to use before printing values. * @param nameValueSeparator the text to use to separate name and value of a field. * @param fieldSeparator the text to use to separate fields. * @param suffix the suffix to use after printing values. * @return an output similar to a tuple. */ String using( String prefix, String nameValueSeparator, String fieldSeparator, String suffix ); /** * This is a convenience method. Invokng this method is the same as invoking * {@link #using(String, String, String, String)} with an empty or {@code null} * name-value separator. * * @param prefix the prefix to use before printing values. * @param fieldSeparator the text to use to separate fields. * @param suffix the suffix to use after printing values. * @return an output similar to a tuple. */ String using( String prefix, String fieldSeparator, String suffix ); } /** * Internal implementation of both the {@link Configuration} * and the {@link Configurator}. * * @author Massimo Coluzzi * @since 2.0.0 */ private static class Config implements Configuration, Configurator { /** * The target object to be returned * by {@link Configuration#target()} */ private final Object target; /** * List of fields to be returned * by {@link Configuration#fields()} */ private final List fields; /** Flag to be returned by {@link Configuration#fullClassPath()} */ public boolean fullClassPath; /** Text to be returned by {@link Configuration#customClassName()} */ public String customClassName; /** * Constructor fith parameters. * * @param target the target object. */ private Config( Object target ) { super(); /* The target object can be null. */ this.target = target; this.fields = new LinkedList<>(); this.fullClassPath = false; this.customClassName = null; } /* ******************* */ /* INTERFACE METHODS */ /* ******************* */ /* OF CONFIGURATION */ /** * {@inheritDoc} */ @Override public Object target() { return target; } /** * {@inheritDoc} */ @Override public Iterable fields() { return fields; } /** * {@inheritDoc} */ @Override public boolean fullClassPath() { return fullClassPath; } /** * {@inheritDoc} */ @Override public String customClassName() { return customClassName; } /* OF CONFIGURATOR */ /** * {@inheritDoc} */ @Override public Configurator print( Object... values ) { if( IsNot.empty(values) ) for( Object value : values ) print( null, value ); return this; } /** * {@inheritDoc} */ @Override public Configurator print( String key, Object value ) { fields.add( new Field(key, value) ); return this; } /** * {@inheritDoc} */ @Override public Configurator withNoClassName() { this.customClassName = ""; return this; } /** * {@inheritDoc} */ @Override public Configurator withFullClassName() { this.fullClassPath = true; return this; } /** * {@inheritDoc} */ @Override public Configurator withCustomClassName( String value ) { this.customClassName = String.valueOf( value ); return this; } /** * {@inheritDoc} */ @Override public String like( Printer printer ) { return printer.apply( this ); } /** * {@inheritDoc} */ @Override public String likeEclipse() { return ToStringOutput.using( this, "[", "=", ", ", "]" ); } /** * {@inheritDoc} */ @Override public String likeIntellij() { return ToStringOutput.using( this, "{", "=", ", ", "}" ); } /** * {@inheritDoc} */ @Override public String likeFunction() { return ToStringOutput.using( this, "(", ":", ", ", ")" ); } /** * {@inheritDoc} */ @Override public String likeTuple() { return ToStringOutput.using( this, "<", ":", ", ", ">" ); } /** * {@inheritDoc} */ @Override public String using( String prefix, String nameValueSeparator, String fieldSeparator, String suffix ) { return ToStringOutput.using( this, prefix, nameValueSeparator, fieldSeparator, suffix ); } /** * {@inheritDoc} */ @Override public String using( String prefix, String fieldSeparator, String suffix ) { return ToStringOutput.using( this, prefix, null, fieldSeparator, suffix ); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy