玩了一段时间后,我终于找到了一个99% 的解决方案。
好消息:有可能。
坏消息:这是 DIY。我找不到任何有用的方法来实现我想要的。
以下帖子应概述有关我的问题的解决方案。可能有更好、更有效或更简单的解决方案,但不幸的是,围绕 eclipse 验证框架的文档非常薄 - 所以我想分享我的解决方案 - 接受它,改进它 - 或者忽略它:)
首先,您应该了解我试图解决的实际问题。因此,我提供了简短的 sn-ps,而不涉及验证器或我的代码线路的太多细节:
在我的项目中,我使用的是 Hibernate——因此很多类都使用 @Entity 注释。当使用 Hibernate 和 LazyLoadingone 时,需要(手动)确保 PersistentBags 在访问时被初始化。
在我们的应用程序中,LazyEntity 类中有一个名为initializeCollection(Collection c) 的方法,它处理它周围的一切。
这导致了一个逻辑合约我的验证器应该验证:
- 只要有一个带有
@Entity 注释的class,并且该类在其任何集合中使用FetchType.LAZY,必须满足两个约束:
- A.) 类 - 或其任何祖先 - 需要扩展
LazyEntity。
- B.) 有问题的
collection 的getter 需要在返回collection 之前调用initializeCollection()。
我将重点关注B 点,因为这是验证问题出现的地方:如何重新验证实际实体,当它的祖先发生变化时?
我修改了实际的验证方法,有两个IFiles作为属性:
public void checkLazyLoadingViolations(IFile actualFile, IFile triggeredFile) {
//validation of actualFile takes place here
}
增量构建器和增量构建器都像这样调用这个方法:
class LazyLoadingResourceVisitor implements IResourceVisitor {
public boolean visit(IResource resource) {
if (resource instanceof IFile) {
checkLazyLoadingViolations((IFile) resource, (IFile) resource);
}
// return true to continue visiting children.
return true;
}
}
现在 - 在第一步中 - 验证器本身正在注意验证 actualFile 并冒泡继承树以验证任何父文件。如果验证器命中最顶层父级,但没有找到所需的扩展,则放置一个额外的标记。
标记的放置是通过以下方法进行的。 如果应该放置标记的文件与 eclipse 调用验证的文件不同,IMarker.USER_EDITABLE 属性用于存储调用验证的文件的路径(在为了重新触发验证):
/**
* Creates a Marker in the give IFile, considering if it should be a direct
* marker, or a dependency marker, which our Validator can resolve later.
*
* @param actualFile
* The file that is currently validated.
* @param triggeredFile
* The file on which eclipse invoked the validation.
* @param message
* The message for the Marker.
* @param lineNumber
* the line number, where the Marker should appear.
* @param severity
* the severity of the marker.
* @param callbackPath
* The full path to the file that should be validated, when the
* marker is revalidated.
*/
public void addMarker(IFile actualFile, IFile triggeredFile,
String message, int lineNumber, int severity, String callbackPath) {
try {
IMarker marker = actualFile.createMarker(MARKER_TYPE);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber == -1 ? 1
: lineNumber);
if (callbackPath != null) {
marker.setAttribute(IMarker.USER_EDITABLE, "callback:"
+ triggeredFile.getFullPath());
}
} catch (CoreException e) {
// eclipse made a boo boo.
}
}
现在,设置了验证错误:每个实际类都包含其错误 - 如果继承树中的验证失败,父类也包含一个标记:
(本例中为AdminUser extends TestUser)
当验证器因更改而在“父”文件上触发时,它会抓取所有标记,并检查标记是否提供 callback 属性。如果是这样,验证器会调用资源的验证而不是,而不仅仅是验证父级:
IMarker[] markers = null;
try {
markers = actualFile.findMarkers(IMarker.PROBLEM, true,
IResource.DEPTH_INFINITE);
for (IMarker m : markers) {
// Our marker type?
if (m.getType().equals(MARKER_TYPE)) {
// dependent resource defined?
if (m.getAttribute(IMarker.USER_EDITABLE) != null) {
if (m.getAttribute(IMarker.USER_EDITABLE)
.toString().startsWith("callback:")) {
String otherFile = m
.getAttribute(IMarker.USER_EDITABLE)
.toString().replace("callback:", "");
// call validation for that file as well.
// (recursion)
String relOther = otherFile.split(Pattern.quote(actualFile.getProject().getFullPath().toString()))[1];
IFile fileToValidateAsWell = actualFile
.getProject().getFile(relOther);
//remove old markers!
deleteMarkers(fileToValidateAsWell);
//revalidate - which has no impact but triggering the root-resource again!
//this will recreate the just deleted markers if problem is not resolved.
checkLazyLoadingViolations(
fileToValidateAsWell, triggeredFile);
}
}
}
}
} catch (CoreException e1) {
}
最后,对继承树中 root 文件的更改会导致 leaf 文件被重新验证:
- 等等。正确调用
initializeCollection-Method 时,完全没有错误:)
目前唯一的权衡是:IF父文件有效 - 并被修改为无效 - 它不会重新触发叶的验证,因为没有 error-marker 包含任何回调信息。
第一次执行完整构建时会出现该错误。 - 目前,我可以忍受。
简而言之逻辑
- 如果经过验证的资源是叶子:
- 在叶子中放置标记
- 将标记放在最顶层的父级中,同时添加
callback link 作为标记属性。
- 如果经过验证的资源是 root
- 删除标记li>
- 在现有标记内
callback link 提供的链接叶 上调用验证,实际情况为1,并在适用时重新创建所有标记。