Copyright (c) 2008, 2019 Mateusz Matela and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: Mateusz Matela - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070 Red Hat Inc. - moved to jdt.core.manipulation
/******************************************************************************* * Copyright (c) 2008, 2019 Mateusz Matela and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * Mateusz Matela <mateusz.matela@gmail.com> - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070 * Red Hat Inc. - moved to jdt.core.manipulation *******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationMessages;

A class used for parsing the toString() template and storing the results.

The template is divided into four parts:

  • Beginning - all the characters from the beginning of the template (inclusively) to the first occurrence of any {$member.*} variable (exclusively). This part can contain only ${object.*} variables and is used to generate the beginning of the generated String.
  • Body - all the characters from the first occurrence of any ${member.*} variable to the variable directly preceding the ${otherMembers}, inclusively. The content of this part is used once for every processed member. All template variables are available (except for ${otherMembers}).
  • Separator
  • - all the characters from the template variable directly preceding the ${otherMembers} to the ${otherMembers}, exclusively. This part does not contain template variables and is used to separate members in the generated String.
  • Ending - all the characters from the occurrence of the ${otherMembers} variable (exclusively) to the end of the template (inclusively). This part can also contain only ${object.*} variables.

Note: for the template to work properly, it must contain at least one ${member.*} variable and exactly one ${otherMembers} variable. Additionally, no ${member.*} variables can follow the ${otherMembers} variable.

Since:3.5
/** * <p> * A class used for parsing the toString() template and storing the results. * </p> * <p> * The template is divided into four parts: * <ul> * <li><b>Beginning</b> - all the characters from the beginning of the template (inclusively) to the * first occurrence of any <code>{$member.*}</code> variable (exclusively). This part can contain * only <code>${object.*}</code> variables and is used to generate the beginning of the generated * <code>String</code>.</li> * <li><b>Body</b> - all the characters from the first occurrence of any <code>${member.*}</code> * variable to the variable directly preceding the <code>${otherMembers}</code>, inclusively. The * content of this part is used once for every processed member. All template variables are * available (except for <code>${otherMembers}</code>). * <li><b>Separator</b></li> - all the characters from the template variable directly preceding the * <code>${otherMembers}</code> to the <code>${otherMembers}</code>, exclusively. This part does not * contain template variables and is used to separate members in the generated <code>String</code>. * <li><b>Ending</b> - all the characters from the occurrence of the <code>${otherMembers}</code> * variable (exclusively) to the end of the template (inclusively). This part can also contain only * <code>${object.*}</code> variables.</li> * </ul> * </p> * <p> * Note: for the template to work properly, it must contain at least one <code>${member.*}</code> * variable and exactly one <code>${otherMembers}</code> variable. Additionally, no * <code>${member.*}</code> variables can follow the <code>${otherMembers}</code> variable. * </p> * * @since 3.5 */
public class ToStringTemplateParser { protected String[] beginning; protected String[] body; protected String separator; protected String[] ending; protected Map<String, String> descriptions;
The variable that inserts the name of the object's class
/** The variable that inserts the name of the object's class **/
public final static String OBJECT_NAME_VARIABLE= "${object.className}"; //$NON-NLS-1$
The variable that inserts a call to this.getClass.getName()
/** The variable that inserts a call to <code>this.getClass.getName()</code> **/
public final static String OBJECT_GET_NAME_VARIABLE= "${object.getClassName}"; //$NON-NLS-1$
The variable that inserts a call to super.toString()
/** The variable that inserts a call to <code>super.toString()</code> **/
public final static String OBJECT_SUPER_TOSTRING_VARIABLE= "${object.superToString}"; //$NON-NLS-1$
The variable that inserts a call to this.hashCode()
/** The variable that inserts a call to <code>this.hashCode()</code> **/
public final static String OBJECT_HASHCODE_VARIABLE= "${object.hashCode}"; //$NON-NLS-1$
The variable that inserts a call to System.identityHashCode(this)
/** The variable that inserts a call to <code>System.identityHashCode(this)</code> **/
public final static String OBJECT_SYSTEM_HASHCODE_VARIABLE= "${object.identityHashCode}"; //$NON-NLS-1$
The variable that inserts the member name
/** The variable that inserts the member name **/
public final static String MEMBER_NAME_VARIABLE= "${member.name}"; //$NON-NLS-1$
The variable that inserts the member name followed by parenthesis in case of methods
/** The variable that inserts the member name followed by parenthesis in case of methods **/
public final static String MEMBER_NAME_PARENTHESIS_VARIABLE= "${member.name()}"; //$NON-NLS-1$
The variable that inserts the values of a member
/** The variable that inserts the values of a member **/
public final static String MEMBER_VALUE_VARIABLE= "${member.value}"; //$NON-NLS-1$
The variable used for determining separator between members
/** The variable used for determining separator between members **/
private final static String OTHER_MEMBERS_VARIABLE= "${otherMembers}"; //$NON-NLS-1$ private final static String[] OBJECT_RELAED_VARIABLE= { OBJECT_NAME_VARIABLE, OBJECT_GET_NAME_VARIABLE, OBJECT_SUPER_TOSTRING_VARIABLE, OBJECT_HASHCODE_VARIABLE, OBJECT_SYSTEM_HASHCODE_VARIABLE }; private final static String[] MEMBER_RELATED_VARIABLE= { MEMBER_NAME_VARIABLE, MEMBER_NAME_PARENTHESIS_VARIABLE, MEMBER_VALUE_VARIABLE }; private final static String[] OBJECT_AND_MEMBER_RELATED_VARIABLES= { OBJECT_NAME_VARIABLE, OBJECT_GET_NAME_VARIABLE, OBJECT_SUPER_TOSTRING_VARIABLE, OBJECT_HASHCODE_VARIABLE, OBJECT_SYSTEM_HASHCODE_VARIABLE, MEMBER_NAME_VARIABLE, MEMBER_NAME_PARENTHESIS_VARIABLE, MEMBER_VALUE_VARIABLE };
A default template for toString() format
/** A default template for toString() format **/
public final static String DEFAULT_TEMPLATE= "${object.className} [${member.name()}=${member.value}, ${otherMembers}]"; //$NON-NLS-1$
Variables that can be used in toSting() format template
/** Variables that can be used in toSting() format template **/
private final static String[] VARIABLES= { OBJECT_NAME_VARIABLE, OBJECT_GET_NAME_VARIABLE, OBJECT_SUPER_TOSTRING_VARIABLE, OBJECT_HASHCODE_VARIABLE, OBJECT_SYSTEM_HASHCODE_VARIABLE, MEMBER_NAME_VARIABLE, MEMBER_NAME_PARENTHESIS_VARIABLE, MEMBER_VALUE_VARIABLE, OTHER_MEMBERS_VARIABLE };
Descriptions of variables in toString format template
/** Descriptions of variables in toString format template **/
private final static String[] VARIABLE_DESCRIPTIONS= { CodeGenerationMessages.GenerateToStringOperation_objectClassNameVariableDescription, CodeGenerationMessages.GenerateToStringOperation_objectClassGetNameVariableDescription, CodeGenerationMessages.GenerateToStringOperation_objectSuperToStringVariableDescription, CodeGenerationMessages.GenerateToStringOperation_objectHashCodeVariableDescription, CodeGenerationMessages.GenerateToStringOperation_objectIdentityHashCodeVariableDescription, CodeGenerationMessages.GenerateToStringOperation_memberNameVariableDescription, CodeGenerationMessages.GenerateToStringOperation_memberNameParenthesesVariableDescription, CodeGenerationMessages.GenerateToStringOperation_memberValueVariableDescription, CodeGenerationMessages.GenerateToStringOperation_otherFieldsVariableDescription };
This method is used in parseTemplate(String) to determine what member specific variables are expected in a template.
Returns:member related variables recognized by this parser
/** * This method is used in {@link #parseTemplate(String)} to determine what member specific * variables are expected in a template. * * @return member related variables recognized by this parser */
protected String[] getMemberRelatedVariables() { return ToStringTemplateParser.MEMBER_RELATED_VARIABLE; }
This method is used in parseTemplate(String) to determine what object related variables are expected in a template.
Returns:object related variables recognized by this parser
/** * This method is used in {@link #parseTemplate(String)} to determine what object related * variables are expected in a template. * * @return object related variables recognized by this parser */
protected String[] getObjectRelatedVariables() { return ToStringTemplateParser.OBJECT_RELAED_VARIABLE; }
This method is used in parseTemplate(String). It returns all variables returned by getMemberRelatedVariables() and getObjectRelatedVariables() (sum of sets).
Returns:member and object related variables recognized by this parser (all variables but {$otherMembers})
/** * This method is used in {@link #parseTemplate(String)}. It returns all variables returned by * {@link #getMemberRelatedVariables()} and {@link #getObjectRelatedVariables()} (sum of sets). * * @return member and object related variables recognized by this parser (all variables but * {$otherMembers}) */
protected String[] getObjectAndMemberRelatedVariables() { return ToStringTemplateParser.OBJECT_AND_MEMBER_RELATED_VARIABLES; } public void parseTemplate(String template) { String[] emptyArray= new String[0]; int beginningEnd= firstOccuranceOf(template, getMemberRelatedVariables()); if (beginningEnd >= 0) { beginning= extractElements(template.substring(0, beginningEnd), getObjectRelatedVariables()).toArray(emptyArray); } else { beginningEnd= 0; beginning= emptyArray; } int endingStart= template.indexOf(ToStringTemplateParser.OTHER_MEMBERS_VARIABLE); if (endingStart == -1) endingStart= template.length(); ArrayList<String> bodyList= extractElements(template.substring(beginningEnd, endingStart), getObjectAndMemberRelatedVariables()); try { separator= bodyList.get(bodyList.size() - 1); bodyList.remove(bodyList.size() - 1); } catch (Exception e) { separator= ""; //$NON-NLS-1$ } body= bodyList.toArray(emptyArray); ending= extractElements(template.substring(endingStart + ToStringTemplateParser.OTHER_MEMBERS_VARIABLE.length()), getObjectRelatedVariables()).toArray(emptyArray); } protected int firstOccuranceOf(String template, String[] wantedVariables) { int result= -1; for (int i= 0; i < wantedVariables.length; i++) { int indexOf= template.indexOf(wantedVariables[i]); if (result == -1 || (indexOf > 0 && indexOf < result)) result= indexOf; } return result; } protected ArrayList<String> extractElements(String template, String[] wantedVariables) { ArrayList<String> result= new ArrayList<>(); while (true) { if (template.length() == 0) break; String foundVariable= null; int variablePosition= template.length(); for (int i= 0; i < wantedVariables.length; i++) { int position= template.indexOf(wantedVariables[i]); if (position >= 0 && position < variablePosition) { variablePosition= position; foundVariable= wantedVariables[i]; } } if (variablePosition == template.length()) { result.add(template); break; } else { if (variablePosition != 0) result.add(template.substring(0, variablePosition)); result.add(foundVariable); template= template.substring(variablePosition + foundVariable.length()); } } return result; } public String[] getBeginning() { return beginning; } public String[] getBody() { return body; } public String[] getEnding() { return ending; } public String getSeparator() { return separator; } public Map<String, String> getVariableDescriptions() { if (descriptions == null) { descriptions= new HashMap<>(); for (int i= 0; i < ToStringTemplateParser.VARIABLES.length; i++) descriptions.put(ToStringTemplateParser.VARIABLES[i], ToStringTemplateParser.VARIABLE_DESCRIPTIONS[i]); } return descriptions; } public String[] getVariables() { return ToStringTemplateParser.VARIABLES; } }