Java tutorial
/* * 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.UserPreferenceUtil.getCompareToCommentsType; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.IBuffer; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeHierarchy; import org.eclipse.jdt.core.JavaModelException; import net.sf.guavaeclipse.dto.MethodInsertionPoint; import net.sf.guavaeclipse.preferences.CompareToCommentsType; import net.sf.guavaeclipse.utils.Utils; public class CompareMethodCreator extends AbstractMethodCreator { private final CompareToCommentsType compareToCommentsType; public CompareMethodCreator(MethodInsertionPoint insertionPoint, List<String> fields) throws JavaModelException { super(insertionPoint, fields); compareToCommentsType = getCompareToCommentsType(); } @Override public void generate() throws JavaModelException { super.generate(); addImplementsComparable(); } @SuppressWarnings("rawtypes") @Override protected String getMethodContent() throws JavaModelException { StringBuilder content = new StringBuilder(); content.append("@Override\n"); content.append("public int compareTo("); String variableName = "that"; final IType currentClass = insertionPoint.getInsertionType(); IType parentCompareToClass = getParentCompareToClass(currentClass); if (parentCompareToClass != null) { content.append(parentCompareToClass.getElementName()); } else { content.append(currentClass.getElementName()); } content.append(" " + variableName + "){\n"); if (parentCompareToClass != null) { content.append(" if ( !( that instanceof " + currentClass.getElementName() + ")) {\n"); content.append(" // XXX check \n"); content.append(" throw new RuntimeException(\"that is not of type " + currentClass.getFullyQualifiedName() + "\");\n"); content.append(" } \n"); content.append("\n"); content.append(currentClass.getElementName() + " obj = (" + currentClass.getElementName() + ") " + variableName + ";"); variableName = "obj"; } StringBuilder commentSection = null; StringBuilder comparisonChain = new StringBuilder(); comparisonChain.append(" return ComparisonChain.start()\n"); if (parentCompareToClass != null) { comparisonChain .append(" // XXX implement parent compare by yourself. This code won't work .compare((") .append(parentCompareToClass.getElementName()).append(") this, (") .append(parentCompareToClass.getElementName()).append(") ").append(variableName).append(")\n"); } for (Iterator<String> iterator = fields.iterator(); iterator.hasNext();) { String field = iterator.next(); String commentMsg = ""; boolean appendField = false; List<IField> sample = Utils.getFields(currentClass); for (Iterator s = sample.iterator(); s.hasNext();) { IField iField = (IField) s.next(); if (iField.getElementName().equals(field)) { // System.out.println("ElementName="+iField.getElementName()); // handling arrays... if (iField.getTypeSignature().startsWith("[")) { commentMsg = "is an Array! and they are not comparable by default"; appendField = false; break; } // handling primitives if (iField.getTypeSignature().length() == 1) { appendField = true; break; } String[][] type = iField.getDeclaringType().resolveType( iField.getTypeSignature().substring(1, iField.getTypeSignature().length() - 1)); if (type != null) { String fullQualifiedClassName = type[0][0] + "." + type[0][1]; // System.out.println("Searching for Class = "+fullQualifiedClassName); if ("java.lang.Object".equals(fullQualifiedClassName)) { commentMsg = "java.lang.Object is not comparable"; appendField = false; break; } IType findType = iField.getJavaProject().findType(fullQualifiedClassName); if (findType != null) { if (doesImplementsComparable(findType)) { appendField = true; } else { commentMsg = " does not implements java.lang.Comparable"; appendField = false; } } else { appendField = false; } break; } else { appendField = true; } } } if (appendField) { // System.out.println(field +" isComparable"); comparisonChain.append(" .compare(this.").append(field).append(", " + variableName + ".") .append(field).append(")\n"); } else { // System.out.println(field +" NOT Comparable"); switch (compareToCommentsType) { case EVERY_FIELD_COMMENT: if (commentMsg == null || commentMsg.trim().isEmpty()) { commentMsg = "is not comparable"; } comparisonChain.append("// XXX field '" + field + "' " + commentMsg + " \n"); break; case ONLY_ONE_COMMENT: if (commentSection == null) { commentSection = new StringBuilder(); } if (commentSection.length() == 0) { commentSection.append( "// XXX check the comment lines, because variables do not implement java.lang.Comparable or they are not comparable at all like arrays \n"); } case NO_COMMENTS: // do nothing because user wants no comment break; } comparisonChain.append("//.compare(this.").append(field).append(", " + variableName + ".") .append(field).append(")\n"); } // System.out.println("***************************"); } comparisonChain.append(" .result();\n"); if (commentSection != null) { content.append(commentSection); } content.append(comparisonChain); content.append("}"); return content.toString(); } @Override protected String getPackageToImport() { return "com.google.common.collect.ComparisonChain"; } @Override protected String getMethodToDelete() { return "compareTo"; } private IType getParentCompareToClass(final IType currentClass) throws JavaModelException { ITypeHierarchy a = currentClass.newSupertypeHierarchy(new NullProgressMonitor()); IType[] allSuperClasses = a.getAllSuperclasses(currentClass); for (int i = 0; i < allSuperClasses.length; i++) { IType superClass = allSuperClasses[i]; if ("java.lang.Object".equals(superClass.getFullyQualifiedName())) { // reached end return null; } IMethod[] methods = superClass.getMethods(); for (int j = 0; j < methods.length; j++) { IMethod method = methods[i]; if ("compareTo".equals(method.getElementName())) { return superClass; } } } return null; } private void addImplementsComparable() throws JavaModelException { ICompilationUnit compilationUnit = getCompilationUnit(); if (compilationUnit != null) addImplementsComparable(compilationUnit.getTypes()[0]); } private boolean doesImplementsComparable(IType type) throws JavaModelException { // get hierarchy ITypeHierarchy hierarchy = type.newTypeHierarchy(null); // hierarchy.getRootInterfaces(); // get interfaces starting from superclass IType[] interfaces = hierarchy.getAllInterfaces(); // does superclass implements comparable? // System.out.println("interfaces for "+type.getElementName()+" = "+interfaces.length); for (int j = 0; j < interfaces.length; j++) { // System.out.println(" "+interfaces[j].getKey()); if (interfaces[j].getFullyQualifiedName().equals("java.lang.Comparable")) //$NON-NLS-1$ { return true; } } return false; } private void addImplementsComparable(IType type) throws JavaModelException { // does class already implements comparable? IType[] interfaces = type.newSupertypeHierarchy(null).getAllInterfaces(); for (int j = 0, size = interfaces.length; j < size; j++) { if (interfaces[j].getFullyQualifiedName().equals("java.lang.Comparable")) //$NON-NLS-1$ { return; } } // find class declaration ISourceRange nameRange = type.getNameRange(); // no declaration?? if (nameRange == null) { return; } // offset for END of class name int offset = nameRange.getOffset() + nameRange.getLength(); IBuffer buffer = type.getCompilationUnit().getBuffer(); String contents = buffer.getText(offset, buffer.getLength() - offset); // warning, this doesn't handle "implements" and "{" contained in // comments in the middle of the declaration! int indexOfPar = contents.indexOf("{"); //$NON-NLS-1$ contents = contents.substring(0, indexOfPar); int indexOfImplements = contents.indexOf("implements"); //$NON-NLS-1$ if (indexOfImplements > -1) { buffer.replace(offset + indexOfImplements + "implements".length()//$NON-NLS-1$ , 0, " Comparable<" + type.getElementName() + ">,"); //$NON-NLS-1$ } else { buffer.replace(offset, 0, " implements Comparable<" + type.getElementName() + ">"); //$NON-NLS-1$ } buffer.save(null, false); buffer.close(); } }