1
我正在使用一個項目,在那裏我有許多其他模型'B','C'等參考的EMF模型'A'等。我想要的是我想要爲這些資源提供重命名功能。所以當用戶重命名'A'時,其引用必須更新。EMF資源的重命名功能
請提供一些想法,如果有任何框架工作,或者我必須獲取所有的引用,然後以編程方式迭代和更新引用。
我正在使用一個項目,在那裏我有許多其他模型'B','C'等參考的EMF模型'A'等。我想要的是我想要爲這些資源提供重命名功能。所以當用戶重命名'A'時,其引用必須更新。EMF資源的重命名功能
請提供一些想法,如果有任何框架工作,或者我必須獲取所有的引用,然後以編程方式迭代和更新引用。
我以另一種方式解決了同樣的問題。
最根本的問題是引用的資源文件可能會被重命名,這會中斷引用。
而不是自動更新所有引用的重構,我創建了一個修復文件引用命令,用戶可以在編輯的模型上調用該命令。
的命令執行下列步驟操作:
如果你仍然想做一個重構,我認爲你可以使用我的代碼作爲一個起點。
/**
* Locates and fixes unresolved references in a model.
*/
public class ReferenceRepairer {
public static final String COMMAND_ID = Activator.PLUGIN_ID + ".commands.repairReferences";
/**
* 1) Prompts the user to select a missing resource to repair
* 2) Prompts the user to select a replacement file
* 3) Updates all objects in the model with a proxy URI that matches the missing resource. Replaces proxies
* with resolved objects in the new resource.
*/
public static void repairResourceReference(Shell shell, EditingDomain editingDomain) {
Resource res = promptMissingResource(shell, editingDomain);
if (res == null) return;
IFile newFile = promptReplacementFile(shell);
if (newFile == null) return;
repairReferences(editingDomain, res, URI.createPlatformResourceURI(newFile.getFullPath().toString(), true));
}
private static void repairReferences(final EditingDomain editingDomain, Resource missingRes, final URI newUri) {
URI missingUri = missingRes.getURI();
// Create new resource for the replacement file
Resource newRes = editingDomain.getResourceSet().getResource(newUri, true);
Map<EObject, Collection<Setting>> proxies = UnresolvedProxyCrossReferencer.find(editingDomain.getResourceSet());
CompoundCommand repairRefsCommand = new CompoundCommand("Repair references") {
/**
* Disallow undo. The model changes could be undone, but it seems impossible to
* recreate a non-existent resource in the resource set.
*/
@Override
public boolean canUndo() {
return false;
}
};
// Resolve all proxies from this resource and repair reference to those objects
for (Entry<EObject, Collection<Setting>> entry : proxies.entrySet()) {
EObject proxy = entry.getKey();
URI proxyUri = EcoreUtil.getURI(proxy);
if (!proxyUri.trimFragment().equals(missingUri)) continue;
EObject resolved = newRes.getEObject(proxyUri.fragment());
if (resolved.eIsProxy()) continue;
// Update all objects that have references to the resolved proxy
for (Setting sett : entry.getValue()) {
if (sett.getEStructuralFeature().isMany()) {
@SuppressWarnings("unchecked")
EList<Object> valueList = (EList<Object>) sett.get(true);
int proxyIx = valueList.indexOf(proxy);
repairRefsCommand.append(SetCommand.create(editingDomain,
sett.getEObject(), sett.getEStructuralFeature(), resolved, proxyIx));
} else {
repairRefsCommand.append(SetCommand.create(editingDomain,
sett.getEObject(), sett.getEStructuralFeature(), resolved));
}
}
}
if (!repairRefsCommand.isEmpty()) {
editingDomain.getCommandStack().execute(repairRefsCommand);
}
// Remove the
editingDomain.getResourceSet().getResources().remove(missingRes);
}
private static IFile promptReplacementFile(Shell shell) {
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(shell,
new WorkbenchLabelProvider(), new WorkbenchContentProvider());
dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
dialog.setTitle("Select Replacement Resource");
dialog.setMessage("Select a file which will replace the missing file.");
dialog.setValidator(new ISelectionStatusValidator() {
@Override
public IStatus validate(Object[] selection) {
if (selection.length == 0 || !(selection[0] instanceof IFile)) {
return ValidationStatus.error("The selected object is not a file.");
}
return new Status(IStatus.OK, Activator.PLUGIN_ID, "");
}
});
if (dialog.open() != Window.OK) return null;
return (IFile) dialog.getFirstResult();
}
private static Resource promptMissingResource(Shell shell, EditingDomain editingDomain) {
ElementListSelectionDialog dialog = new ElementListSelectionDialog(shell,
new LabelProvider() {
@Override
public String getText(Object elem) {
return ((Resource) elem).getURI().toString();
}
})
{
/** Make dialog OK button enabled when there are errors, instead of vise-versa. */
@Override
protected void updateButtonsEnableState(IStatus status) {
Button okButton = getOkButton();
if (okButton != null && !okButton.isDisposed()) {
okButton.setEnabled(!status.isOK());
}
}
/** Disable filter text field */
@Override
protected Text createFilterText(Composite parent) {
Text text = super.createFilterText(parent);
text.setSize(0, 0);
text.setLayoutData(GridDataFactory.swtDefaults().exclude(true).create());
text.setVisible(false);
return text;
}
};
dialog.setTitle("Select Missing Resource");
dialog.setMessage(
"Select a URI of a missing resource file that should be replaced by an URI to an existing file.");
dialog.setElements(getMissingResources(editingDomain.getResourceSet().getResources()).toArray());
if (dialog.open() != Window.OK) return null;
return (Resource) dialog.getFirstResult();
}
private static List<Resource> getMissingResources(List<Resource> resources) {
List<Resource> missingResources = new ArrayList<>();
for (Resource res : resources) {
try {
if (res.getURI().isPlatformPlugin()) continue;
URL url = FileLocator.toFileURL(new URL(res.getURI().toString()));
java.net.URI uri = new java.net.URI(url.getProtocol(), "", "/" + url.getPath(), null);
if (!Files.exists(Paths.get(uri))) {
missingResources.add(res);
}
} catch (InvalidPathException | IOException | URISyntaxException exc) {
// Ignore. There mighe be weird Sirius resource in the resources set which we can't recognice
}
}
return missingResources;
}
}
您是否嘗試玩過EMF觀察員/通知?您可以註冊觀察員並對特定事件作出反應(例如,資源上的一組名稱特徵)。 – 2015-02-24 09:38:12
當我更改任何屬性的名稱時,我是否可以知道要在「B」,「C」等中執行哪種更新?如果該屬性值在引用中被認爲是FQN,那麼它會自動啓動更新。 – 2015-04-05 03:08:25