/******************************************************************************* * Copyright (c) 2012, 2015 Spring IDE Developers * 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: * Spring IDE Developers - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.data.internal.validation; import java.lang.reflect.Method; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.ILocalVariable; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.springframework.ide.eclipse.core.SpringCore; import org.springframework.ide.eclipse.core.StringUtils; import org.springframework.ide.eclipse.core.model.IModelElement; import org.springframework.ide.eclipse.core.model.java.JavaModelSourceLocation; import org.springframework.ide.eclipse.core.model.validation.IValidationContext; import org.springframework.ide.eclipse.core.model.validation.IValidationRule; import org.springframework.ide.eclipse.core.model.validation.ValidationProblemAttribute; import org.springframework.ide.eclipse.data.jdt.core.RepositoryInformation; /** * @author Terry Denney * @since 3.2.0 */ public class InvalidParameterTypeRule implements IValidationRule<CompilationUnit, SpringDataValidationContext> { public static final String PROBLEM_ID = "INVALID_PARAMETER_TYPE"; public static final String PROPERTY_TYPE_ATTR = "PROPERTY_TYPE_ATTR"; public static final String PROPERTY_TYPE_PACKAGE_ATTR = "PROPERTY_TYPE_PACKAGE_ATTR"; public boolean supports(IModelElement element, IValidationContext context) { if (!(context instanceof SpringDataValidationContext)) { return false; } if (element instanceof CompilationUnit) { CompilationUnit cu = (CompilationUnit) element; ITypeRoot typeRoot = cu.getTypeRoot(); if (typeRoot == null) { return false; } IType type = typeRoot.findPrimaryType(); if (type == null) { return false; } // Skip non-interfaces try { if (type == null || !type.isInterface() || type.isAnnotation()) { return false; } } catch (JavaModelException e) { SpringCore.log(e); return false; } // Skip non-spring-data repositories if (!RepositoryInformation.isSpringDataRepository(type)) { return false; } // resolve repository information and generate problem markers RepositoryInformation information = new RepositoryInformation(type); Class<?> domainClass = information.getManagedDomainClass(); if (domainClass == null) { return false; } return true; } return false; } public void validate(CompilationUnit element, SpringDataValidationContext context, IProgressMonitor monitor) { ITypeRoot typeRoot = element.getTypeRoot(); IType type = typeRoot.findPrimaryType(); // resolve repository information and generate problem markers RepositoryInformation information = new RepositoryInformation(type); Class<?> domainClass = information.getManagedDomainClass(); if (domainClass == null) { return; } try { for (IMethod method : type.getMethods()) { String methodName = method.getElementName(); if (methodName.startsWith("findBy")) { String propertyName = StringUtils.uncapitalize(methodName .substring("findBy".length())); ILocalVariable[] params = method.getParameters(); if (params.length == 1) { String paramTypeSignature = params[0].getTypeSignature(); Method propertyMethod = null; try { propertyMethod = domainClass.getMethod("get" + StringUtils.capitalize(propertyName)); } catch (NoSuchMethodException e) { // not a property method... ignore continue; } if (propertyMethod != null) { Class<?> propertyReturnType = propertyMethod.getReturnType(); String propertySimpleType = propertyReturnType.getSimpleName(); String paramSimpleType = Signature.getSignatureSimpleName(paramTypeSignature); if (propertySimpleType != null && !(propertySimpleType.equals(paramSimpleType))) { element.setElementSourceLocation(new JavaModelSourceLocation(params[0])); ISourceRange paramSourceRange = params[0].getSourceRange(); ValidationProblemAttribute start = new ValidationProblemAttribute( IMarker.CHAR_START, paramSourceRange.getOffset()); ValidationProblemAttribute end = new ValidationProblemAttribute( IMarker.CHAR_END, paramSourceRange.getOffset() + paramSourceRange.getLength()); ValidationProblemAttribute problemId = new ValidationProblemAttribute(IMarker.PROBLEM, PROBLEM_ID); ValidationProblemAttribute propertyType = new ValidationProblemAttribute(PROPERTY_TYPE_ATTR, propertyReturnType.getSimpleName()); String packageName = propertyReturnType.getPackage() != null ? propertyReturnType.getPackage().getName() : ""; ValidationProblemAttribute propertyTypePackage = new ValidationProblemAttribute(PROPERTY_TYPE_PACKAGE_ATTR, packageName); context.warning(element, "SpringDataProbleMarker", "Parameter type (" + paramSimpleType + ") does not match domain class property definition (" + propertySimpleType + ").", new ValidationProblemAttribute[] {start, end, problemId, propertyType, propertyTypePackage}); } } } } } } catch (JavaModelException e) { SpringCore.log(e); } catch (SecurityException e) { SpringCore.log(e); } } }