/* * Copyright 2014 * * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package net.sf.guavaeclipse.creator; import static net.sf.guavaeclipse.preferences.HashCodeStrategyType.ARRAYS_DEEP_HASH_CODE; import static net.sf.guavaeclipse.preferences.HashCodeStrategyType.OBJECTS_HASH_CODE; import static net.sf.guavaeclipse.preferences.HashCodeStrategyType.SMART_HASH_CODE; import java.util.List; import java.util.Map; import net.sf.guavaeclipse.dto.MethodInsertionPoint; import net.sf.guavaeclipse.preferences.HashCodeStrategyType; import net.sf.guavaeclipse.preferences.MethodGenerationStratergy; import net.sf.guavaeclipse.preferences.UserPreferenceUtil; import net.sf.guavaeclipse.utils.Utils; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeHierarchy; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.ToolFactory; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.TextEdit; public abstract class AbstractMethodCreator { protected static final String IMPORT_DECL_OBJECTS = "com.google.common.base.Objects"; protected static final String IMPORT_DECL_ARRAYS = "java.util.Arrays"; protected final MethodInsertionPoint insertionPoint; protected final List<String> fields; protected final MethodGenerationStratergy methodGenerationStratergy; protected final HashCodeStrategyType hcst; public AbstractMethodCreator(MethodInsertionPoint insertionPoint, List<String> fields) throws JavaModelException { this.insertionPoint = insertionPoint; this.fields = fields; this.methodGenerationStratergy = getMethodGenerationStratergy(); this.hcst = getHashCodeStrategyType(); } private MethodGenerationStratergy getMethodGenerationStratergy() throws JavaModelException { MethodGenerationStratergy methodGenerationStratergy = UserPreferenceUtil.getMethodGenerationStratergy(); if (methodGenerationStratergy == MethodGenerationStratergy.SMART_OPTION) { ITypeHierarchy a = this.insertionPoint.getInsertionType().newSupertypeHierarchy(new NullProgressMonitor()); IType superTypes[] = a.getAllSuperclasses(this.insertionPoint.getInsertionType()); if (superTypes.length == 1 && superTypes[0].getKey().equals("Ljava/lang/Object;")) { return MethodGenerationStratergy.DONT_USE_SUPER; } else { return MethodGenerationStratergy.USE_SUPER; } } return methodGenerationStratergy; } private HashCodeStrategyType getHashCodeStrategyType() throws JavaModelException { HashCodeStrategyType hashCodeStrategyType = UserPreferenceUtil.getHashCodeStrategyType(); if (hashCodeStrategyType == SMART_HASH_CODE) { if (Utils.atLeastOneSelectedFieldIsArray(insertionPoint.getInsertionType(), fields)) { hashCodeStrategyType = ARRAYS_DEEP_HASH_CODE; } else { hashCodeStrategyType = OBJECTS_HASH_CODE; } } return hashCodeStrategyType; } public void generate() throws JavaModelException { String content = getMethodContent(); IMethod method = getExistingMethod(getMethodToDelete()); boolean methodDeleted = deleteExistingMethod(method); insertionPoint.getInsertionType().createMethod( formatCode(content), methodDeleted ? null : insertionPoint.getInsertionMember(), true, new NullProgressMonitor()); generateImport(getPackageToImport()); } protected abstract String getMethodContent() throws JavaModelException; protected abstract String getMethodToDelete(); /** * @return the package which is to add as import statement, overwrite if something else as * <code>com.google.common.base.Objects</code> is necessary */ protected String getPackageToImport() { return IMPORT_DECL_OBJECTS; } protected void generateImport(String importStatement) throws JavaModelException { String[] importStatements = importStatement.split(","); ICompilationUnit compilationUnit = getCompilationUnit(); if (compilationUnit != null) { for (String importDecl : importStatements) { compilationUnit.createImport(importDecl, null, new NullProgressMonitor()); } } } protected IMethod getExistingMethod(String methodName) throws JavaModelException { return Utils.getMethod(insertionPoint.getInsertionType(), methodName); } protected ICompilationUnit getCompilationUnit() { IJavaElement parentElement = insertionPoint.getInsertionType().getParent(); if (parentElement == null) { return null; } if (parentElement.getElementType() == 5) { return (ICompilationUnit) parentElement; } return null; } @SuppressWarnings("rawtypes") protected String formatCode(String newCode) { try { Map options = getCompilationUnit().getJavaProject().getOptions(true); final CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(options); TextEdit format = codeFormatter.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, newCode, 0, newCode.length(), 1, null); IDocument document = new Document(newCode); format.apply(document); String formattedCode = document.get(); return formattedCode.replaceAll("\r", ""); } catch (MalformedTreeException e) { e.printStackTrace(); } catch (BadLocationException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return newCode; } protected boolean deleteExistingMethod(IMethod method) throws JavaModelException { if (method != null) { method.delete(true, new NullProgressMonitor()); return true; } return false; } }