vrijdag 4 december 2009

WorkbenchMarkerResolution is fantastic!

One of my ongoing projects that is in beta now for a long time is EulumdatTools, a special purpose editor and workbench for managing, verifying and editing EULUMDAT files. EULUMDAT is a European de facto standard for photometric data files. It describes stuff like manufacturer, product name, lamp type, power consumption and luminous flux distribution for lighting products.

Builder, IMarker and IMarkerResolution2


I used Eclipse to create a Builder, IMarkers and IMarkerResolution2 to create a Validator, Problems view entries and Quick Fix solutions under CTRL/CMD+1 to resolve issues where file were not conforming to standard or incomplete (for the curious: some manufacturers do not provide the Direct Flux Factors).
There are 10 of these Direct Flux Factors in every file, so it would be nice to be able to fix these all in one action.

WorkbenchMarkerResolution to the rescue!

After some research I found that that is easier to implement than I first thought! What you must do is make your Quick Fix code extend WorkbenchMarkerReslution instead of implement IMarkerResolution2.
This means you must implement one extra method: IMarker[] findOtherMarkers(IMarker[] markers). You receive ALL of the markers in the problems view and must return an array of those you can handle in this Quick Fix, this is easy to implement with a loop and a isValidOther() method.
public class ReplaceDFF extends WorkbenchMarkerResolution {

private final IMarker originalMarker;

// use constructor to remember original marker
public ReplaceDFF(final IMarker marker) {
super();
originalMarker = marker;
}

@Override
public IMarker[] findOtherMarkers(IMarker[] markers) {
List<IMarker> others = new ArrayList<IMarker>();
for (IMarker marker : markers) {
if (isValidOther(marker)) {
others.add(marker);
}
}
return others.toArray(new IMarker[0]);
}

@Override
public boolean isValidOther(final IMarker marker) {
// is it the originalMarker, we don't want duplicates!
if(markerToCheck.equals(originalMarker)) {
return false;
}
// is it in the same file as original marker?
if(!marker.getResource().equals(originalMarker.getResource())) {
return false;
}
// is it the same validator?
String checkerName = LightOutputRatioChecker.class.getName();
if(!checkerName.equals(getCheckerName(marker))) {
return false;
}
// is it the same error found?
String checkerMessage = getCheckerMessage(marker);
if(!checkerMessage.startsWith(
LightOutputRatioChecker.DIRECT_RATIO_1))
{
return false;
}
return true;
}
[...]
}

The result is improved usability

Running with this small modification gives us this Quick Fix Dialog:
In practice the values are all correct or more than one is wrong, so handling this in one Quick fix will improve the users productivity in a big way. Click once, save the file and all warnings are gone...

Final notes...

I experimented with various filtering strategies before settling on fixing all similar errors in one file. Using the filters you can also opt to:
  • Fix different errors all in the same file, when your run(IMarker) method can handle different errors.
  • Find all errors in the workspace, letting through all markers with this fix. But then each fix required the file to be opened, so that takes long time and this cannot be cancelled.
  • I may still try to check whether the file is already open and only suggest to apply the fix in these.