我需要查找在其equals()方法中使用JPA ID属性的JPA持久化类。例如,以下类将触发PMD规则违规:
@Entity
public class Foo
{
@Id
private long id;
public boolean equals(Object o)
{
if (o.getClass().equals(Foo.class)) {
Foo other = (Foo) o;
return o.id == id;
}
return false;
}
}
我知道如何使这个查询的各个部分工作,但不知道如何将它组合在一起。所以,例如,我知道如何找到JPA持久化类(假设使用JPA注释):
//ClassOrInterfaceDeclaration/../Annotation/MarkerAnnotation/Name[@Image='Entity']
我知道如何找到使用JPA ID注释注释的字段的声明:
//FieldDeclaration[../Annotation/MarkerAnnotation/Name[@Image='Id']]
同样,我可以在equals()方法中找到一个引用名为'id'的字段的表达式:
//MethodDeclaration[
./MethodDeclarator[@Image='equals'] and
./MethodDeclarator/FormalParameters[1]/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[@Image='Object']
]
/Block//PrimaryExpression/PrimaryPrefix/Name[@Image='id']
我遇到的麻烦是使用表达式查找用@Id注释标记的字段的名称,并在谓词中使用它来查找使用该字段的equals()方法中的行。
这是我对查询的最佳猜测,但它不返回任何节点:
//MethodDeclaration[
./MethodDeclarator[@Image='equals']
and
//MethodDeclarator[count(./FormalParameters)=1]
and
./MethodDeclarator/FormalParameters[1]/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[@Image='Object']
]
/Block//PrimaryExpression/Name[
@Image=ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
../Annotation/MarkerAnnotation/Name/@Image='Id']/VariableDeclarator/VariableDeclaratorId/@Image
]
前7行返回所有名称为“equals”的MethodDeclarations,并采用单个“Object”参数。
下一部分选择该方法中的任何PrimaryExpressions,其Name等于使用“Id”注释注释的字段的名称。 有什么帮助吗?
答案 0 :(得分:1)
好的,我已经弄清楚了......这是我提出的解决方案:
//MethodDeclaration[
MethodDeclarator[
count(FormalParameters/FormalParameter)=1 and
@Image='equals' and
FormalParameters/FormalParameter[1]/Type/ReferenceType/ClassOrInterfaceType[@Image='Object']
]
]
/Block//PrimaryExpression[
PrimaryPrefix/@Image=
ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
../Annotation/MarkerAnnotation/Name/@Image='Id'
] /VariableDeclarator/VariableDeclaratorId/@Image
or
PrimarySuffix/@Image=
ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
../Annotation/MarkerAnnotation/Name/@Image='Id'
] /VariableDeclarator/VariableDeclaratorId/@Image
]
似乎有效。