2015-02-24 3 views
1

Я работаю с проектом, где у меня есть модель EMF «A», на которую ссылаются во многих других моделях «B», «C» ... и т. Д. Я хочу, чтобы я хотел предоставить функцию переименования для этих ресурсов. Поэтому, когда пользователь переименовывает «A», его ссылки должны быть обновлены.Функция переименования для ресурсов EMF

Просьба представить некоторое представление об этом, если для этого есть какая-либо работа с фреймом, или мне нужно получить все ссылки, а затем программно перебрать и обновить ссылки.

+0

Вы пытались сыграть с наблюдателями/уведомлениями EMF? Вы можете регистрировать наблюдателя и реагировать на определенные события (например, как набор функций имени на ресурсе). –

+0

Могу ли я узнать, какое обновление вы хотите выполнять в 'B', 'C' и т. Д., Когда вы меняете имя любого атрибута, и если это значение атрибута рассматривается для FQN в ссылке, то оно автоматически будет обновлено. –

ответ

0

Я решил ту же проблему по-другому.

Основная проблема заключается в том, что ссылочный файл ресурсов может быть переименован, и это нарушает ссылки.

Вместо рефакторинга, который автоматически обновляет все ссылки, я создал команду Repair File References, которую пользователь может вызывать на отредактированной модели.

Команда выполняет следующие действия:

  1. предлагает пользователю выбрать недостающий ресурс для восстановления
  2. Предлагает пользователю выбрать замену файлу
  3. обновляет все объекты в модели, которая имеет прокси URI, который соответствует отсутствующему ресурсу. Заменяет прокси с разрешенными объектами в новом ресурсе.

Если вы все еще хотите сделать рефакторинг, я думаю, вы все равно можете использовать мой код в качестве отправной точки.

/** 
* 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; 
    } 
} 
Смежные вопросы