ToStringTemplateParser.java :  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » corext » codemanipulation » tostringgeneration » Java Open Source

Java Open Source » IDE Eclipse » jdt 
jdt » org » eclipse » jdt » internal » corext » codemanipulation » tostringgeneration » ToStringTemplateParser.java
/*******************************************************************************
 * Copyright (c) 2008 Mateusz Matela and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Mateusz Matela <mateusz.matela@gmail.com> - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070
 *******************************************************************************/
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;

/**
 * <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 descriptions;

  /** 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 <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 <code>super.toString()</code> **/
  public final static String OBJECT_SUPER_TOSTRING_VARIABLE= "${object.superToString}"; //$NON-NLS-1$

  /** 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 <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 **/
  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 **/
  public final static String MEMBER_NAME_PARENTHESIS_VARIABLE= "${member.name()}"; //$NON-NLS-1$

  /** 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 **/
  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 **/
  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 **/
  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 **/
  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 {@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 {@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 {@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= (String[])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 bodyList= extractElements(template.substring(beginningEnd, endingStart), getObjectAndMemberRelatedVariables());

    try {
      separator= (String)bodyList.get(bodyList.size() - 1);
      bodyList.remove(bodyList.size() - 1);
    } catch (Exception e) {
      separator= ""; //$NON-NLS-1$
    }

    body= (String[])bodyList.toArray(emptyArray);
    ending= (String[])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 extractElements(String template, String[] wantedVariables) {
    ArrayList 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 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;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.