commit 4ff11da52f34b700620b1817db3223c7d4b8974f
Author: pplitzner <pplitzner@pplitzner-home-desktop>
Date:   Thu Aug 24 17:11:59 2017 +0200

    ref #6595 Initial commit of migrated/refactored classes (not working)

diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/MultiPageTaxonEditorDataChangeBehaviourE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/MultiPageTaxonEditorDataChangeBehaviourE4.java
new file mode 100644
index 000000000..2822c28df
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/MultiPageTaxonEditorDataChangeBehaviourE4.java
@@ -0,0 +1,121 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.e4;
+
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeEvent;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeEvent.EventType;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.model.AbstractDataChangeBehaviour;
+import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
+
+/**
+ * Implementation if {@link eu.etaxonomy.taxeditor.store.model.IDataChangeBehaviour}
+ * for the {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}.
+ *
+ * TODO make this class a bean and thus configurable by Spring
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class MultiPageTaxonEditorDataChangeBehaviourE4 extends AbstractDataChangeBehaviour implements
+		IDataChangeBehavior {
+	private static final Logger logger = Logger
+			.getLogger(MultiPageTaxonEditorDataChangeBehaviourE4.class);
+
+	private MultiPageTaxonEditorE4 source;
+
+	private TaxonEditorInputE4 input;
+
+	public MultiPageTaxonEditorDataChangeBehaviourE4(
+	        MultiPageTaxonEditorE4 multiPageTaxonEditor) {
+		source = multiPageTaxonEditor;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void reactOnDataChange(CdmDataChangeMap changeEvents) {
+		input = source.getEditorInput();
+
+		// I don't know when this happens but ...
+		if(input.getTaxon() == null) {
+            return;
+        }
+
+		if(changeEvents.sizeByEventType(EventType.UPDATE) > 0){
+			reactOnUpdate(changeEvents.getEvents(EventType.UPDATE));
+		}
+		if(changeEvents.sizeByEventType(EventType.INSERT) > 0){
+			reactOnInsert(changeEvents.getEvents(EventType.INSERT));
+		}
+		if(changeEvents.sizeByEventType(EventType.DELETE) > 0){
+			reactOnDelete(changeEvents.getEvents(EventType.DELETE));
+		}
+	}
+
+
+	/** {@inheritDoc} */
+	//we do not really need this anymore as closing the editors is
+	//now run before the delete operation in DeleteHandler
+	@Override
+	public void reactOnDelete(Vector<CdmDataChangeEvent> events){
+		for(CdmDataChangeEvent event : events){
+			// close open editors
+			if((event.getEntity() instanceof TaxonNode)
+					&& input.getTaxonNode().equals(event.getEntity())){
+				//EditorUtil.close(source);
+				logger.debug("Closing open editor for deleted taxon."); //$NON-NLS-1$
+			}
+		}
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void reactOnUpdate(Vector<CdmDataChangeEvent> events){
+
+		for(CdmDataChangeEvent event : events){
+
+			// update editor title
+			if(event.getEntity() instanceof TaxonName){
+				if(input.getTaxon().getName().equals(event.getEntity())){
+					// set the name of the editor window
+					source.setPartName();
+					logger.debug("Updating title of taxons editor."); //$NON-NLS-1$
+				}
+			}
+			// TODO other stuff to happen
+
+		}
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void reactOnInsert(Vector<CdmDataChangeEvent> events){
+		boolean doRedraw = false;
+		for(CdmDataChangeEvent event : events){
+			// refresh on synonym changes
+			if(input.getTaxon().hasSynonyms() && event.getEntity() instanceof Synonym){
+				Synonym synonym = (Synonym) event.getEntity();
+
+				if(synonym.isSynonymOf(input.getTaxon())){
+					doRedraw = true;
+					break;
+				}
+			}
+		}
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/MultiPageTaxonEditorE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/MultiPageTaxonEditorE4.java
new file mode 100644
index 000000000..9b9368919
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/MultiPageTaxonEditorE4.java
@@ -0,0 +1,452 @@
+/**
+ * Copyright (C) 2007 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+
+package eu.etaxonomy.taxeditor.editor.e4;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.core.commands.operations.UndoContext;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+
+import eu.etaxonomy.cdm.api.application.CdmApplicationState;
+import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
+import eu.etaxonomy.cdm.api.application.CdmChangeEvent.Action;
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage;
+import eu.etaxonomy.taxeditor.editor.ISecuredEditor;
+import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
+import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
+import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.model.DataChangeBridge;
+import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
+import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
+import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
+import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
+import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
+import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class MultiPageTaxonEditorE4
+        implements IPartContentHasFactualData, IConversationEnabled, IPostOperationEnabled, IDirtyMarkable,
+        IPartContentHasDetails, IPartContentHasSupplementalData, ISecuredEditor, IPartContentHasMedia, ITaxonEditor {
+
+    /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
+    public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon"; //$NON-NLS-1$
+
+    private ConversationHolder conversation;
+    private IDataChangeBehavior dataChangeBehavior;
+    private IUndoContext undoContext;
+
+    private TaxonEditorInputE4 input;
+
+    @Inject
+    private ESelectionService selService;
+
+    @Inject
+    private MDirtyable dirty;
+
+    private ISelectionChangedListener selectionChangedListener;
+
+
+    @Inject
+    public MultiPageTaxonEditorE4() {
+        undoContext = new UndoContext();
+
+    }
+
+    /** {@inheritDoc} */
+    @PreDestroy
+    public void dispose() {
+        input.dispose();
+        conversation.unregisterForDataStoreChanges(this);
+        conversation.close();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void addPages() {
+        input = getEditorInput();
+        conversation = input.getConversationHolder();
+        conversation.registerForDataStoreChanges(this);
+
+        try {
+            addPage(Page.NAME.getIndex(), new TaxonNameEditor(this),
+                    getEditorInput());
+
+        } catch (PartInitException e) {
+            MessagingUtils.error(getClass(), e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void pageChange(int newPageIndex) {
+        if(getCurrentPage()==-1){
+            return;
+        }
+        super.pageChange(newPageIndex);
+    }
+
+    /** {@inheritDoc} */
+    @Persist
+    public void doSave(IProgressMonitor monitor) {
+        monitor.beginTask(Messages.MultiPageTaxonEditor_SAVING_EDITOR, 4);
+        try {
+            if (!conversation.isBound()) {
+                conversation.bind();
+            }
+            monitor.worked(1);
+
+            for (IEditorPart editorPage : getPages()) {
+                if (editorPage instanceof TaxonNameEditor) {
+                    if (((TaxonNameEditor) editorPage).checkForEmptyNames()) {
+                        MessageDialog.openWarning(AbstractUtility.getShell(), Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED,
+                                Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE);
+                        return;
+                    }
+                }
+
+                editorPage.doSave(monitor);
+                monitor.worked(1);
+            }
+
+            // commit the conversation and start a new transaction immediately
+
+            input.merge();
+
+            conversation.commit(true);
+            CdmApplicationState.getCurrentDataChangeService()
+            .fireChangeEvent(new CdmChangeEvent(Action.Update, input.getTaxonNode() , MultiPageTaxonEditorE4.class), true);
+            monitor.worked(1);
+
+            this.setDirty(false);
+            monitor.worked(1);
+        } catch (Exception e) {
+            setFocus();
+            MessagingUtils.operationDialog(this, e, TaxeditorEditorPlugin.PLUGIN_ID,Messages.MultiPageTaxonEditor_SAVING_TAXON, Messages.MultiPageTaxonEditor_SAVING_TAXON_MESSAGE);
+            disableEditor(true);
+        } finally {
+            monitor.done();
+        }
+    }
+
+    private void disableEditor(boolean isOnError) {
+        for (IMultiPageTaxonEditorPage editorPage : getPages()) {
+            if(isOnError){
+                editorPage.setOnError();
+            }else {
+                editorPage.setDisabled();
+            }
+        }
+
+        conversation.unregisterForDataStoreChanges(this);
+        conversation.close();
+        setDirty(false);
+    }
+
+    private void setDirty(boolean dirty) {
+        this.dirty.setDirty(dirty);
+    }
+
+    public boolean isDirty() {
+        return dirty.isDirty();
+    }
+
+    public void init(IEditorInput input)
+            throws PartInitException {
+
+        if (!(input instanceof TaxonEditorInputE4)) {
+            throw new PartInitException(
+                    Messages.MultiPageTaxonEditor_INVALID_INPUT);
+        }
+
+        this.input = (TaxonEditorInputE4) input;
+        setPartName();
+    }
+
+    /**
+     * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
+     * text appropriate to the state of the taxon: any taxon that has been saved
+     * will by necessity have a name to display; a new taxon should display
+     * "New taxon" in the editor tab.
+     */
+    protected void setPartName() {
+
+        String partName = null;
+        TaxonName name = getTaxon().getName();
+
+        if (name != null) {
+            partName = name.getTitleCache();
+        }
+
+        if (partName == null || partName.equals("")) { //$NON-NLS-1$
+            partName = (Messages.MultiPageTaxonEditor_NEW_TAXON);
+        }
+
+        //FIXME E4 migrate
+//        setPartName(partName);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Editor pages call this in their postOperation to notify the
+     * MultiPageTaxonEditor of unsaved changes
+     */
+    @Override
+    public void changed(Object element) {
+        // setDirty(true);
+        // if the attribute is null then do not set the dirty flag -> hotfix for the problem that for tasks done in service methods the changes are saved automatically
+        if (element != null){
+            setDirty(true);
+        }
+
+        if (element instanceof TaxonBase) {
+            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
+            AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
+            if (container != null) {
+                container.refresh();
+            }
+        }
+        if (element instanceof TaxonRelationship) {
+            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
+            AbstractGroupedContainer container = page.getContainer(((TaxonRelationship) element).getFromTaxon());
+            if (container != null) {
+                container.refresh();
+            }
+        }
+        //refresh part title
+        //TODO: refresh taxon node in taxon navigator
+        setPartName();
+    }
+
+    @Override
+    public void forceDirty() {
+        changed(null);
+    }
+
+    /**
+     * The accepted taxon that is the input for this editor
+     *
+     * @return the accepted taxon
+     */
+    @Override
+    public Taxon getTaxon() {
+        return input.getTaxon();
+    }
+
+    @Override
+    public ConversationHolder getConversationHolder() {
+        return conversation;
+    }
+
+    public void setConversationHolder(ConversationHolder conversation) {
+        this.conversation = conversation;
+    }
+
+    public IUndoContext getUndoContext() {
+        return undoContext;
+    }
+
+    public void setUndoContext(IUndoContext undoContext) {
+        this.undoContext = undoContext;
+    }
+
+    /** {@inheritDoc} */
+    @Focus
+    public void setFocus() {
+        // logger.warn("Setting focus to editor");
+        // bind the conversation
+        getConversationHolder().bind();
+        input.bind();
+        // pass focus to the active editor page
+        //FIXME E4 migrate
+//        getActiveEditor().setFocus();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void update(CdmDataChangeMap events) {
+        if (dataChangeBehavior == null) {
+            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviourE4(this);
+        }
+
+        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean postOperation(CdmBase objectAffectedByOperation) {
+    		setDirty(true);
+
+        for (IEditorPart editor : this.getPages()) {
+            if (editor instanceof IPostOperationEnabled) {
+                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
+            } else {
+                MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_NOT_ENABLED + editor);
+            }
+        }
+        MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_CALLED);
+
+        return false;
+    }
+
+    /**
+     * Returns an <code>IEditorPart</code> implementation by type
+     *
+     * @param page
+     *            the page type
+     * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
+     *         object.
+     */
+    public IMultiPageTaxonEditorPage getPage(Page page) {
+        for (IEditorPart editor : this.getPages()) {
+            if (editor.getClass().equals(page.getClazz())) {
+                return (IMultiPageTaxonEditorPage) editor;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return a list of <code>AbstractTaxonEditor</code>s registered with this
+     * <code>MultiPageTaxonEditor</code>.
+     *
+     * @return a {@link java.util.List} object.
+     */
+    public List<IMultiPageTaxonEditorPage> getPages() {
+        ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
+        for (int i = 0; i < this.getPageCount(); i++) {
+
+            editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
+        }
+        return editors;
+    }
+
+    /**
+     * Refreshes a certain page of the MultipageTaxonEditor
+     *
+     * @param page
+     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
+     * @return a boolean.
+     */
+    public boolean redraw(Page page) {
+        return redraw(page, true);
+    }
+
+    /**
+     * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
+     * that page
+     *
+     * @param page
+     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
+     * @param focus
+     *            a boolean.
+     * @return a boolean.
+     */
+    public boolean redraw(Page page, boolean focus) {
+        IMultiPageTaxonEditorPage editorPage = getPage(page);
+        return editorPage != null && editorPage.redraw(focus);
+    }
+
+    /**
+     * <p>
+     * onComplete
+     * </p>
+     *
+     * @return a boolean.
+     */
+    @Override
+    public boolean onComplete() {
+        return false;
+    }
+
+    /**
+     * Reloads the data for this
+     */
+    public void reload() {
+        if (isDirty()) {
+            MessagingUtils.warningDialog(Messages.MultiPageTaxonEditor_UNSAVED_DATA, getClass(), Messages.MultiPageTaxonEditor_UNSAVED_DATA_MESSAGE);
+        } else {
+            TaxonEditorInputE4 input = getEditorInput();
+
+            UUID uuid = input.getTaxonNode().getUuid();
+
+            conversation.clear();
+
+            try {
+                TaxonEditorInputE4 newInput = TaxonEditorInputE4.NewInstance(uuid);
+                setInput(newInput);
+                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
+                    editorPart.redraw();
+                }
+            } catch (Exception e) {
+                MessagingUtils.messageDialog(Messages.MultiPageTaxonEditor_REFRESH_ERROR, getClass(), Messages.MultiPageTaxonEditor_REFRESH_ERROR_MESSAGE, e);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput()); //$NON-NLS-1$
+    }
+
+    @Override
+    public boolean permissionsSatisfied() {
+        IEditorPart activeEditor = getActiveEditor();
+        if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
+            return ((ISecuredEditor)activeEditor).permissionsSatisfied();
+        }
+        return true;
+    }
+
+    @Override
+    public boolean canAttachMedia() {
+        return true;
+    }
+
+    public TaxonEditorInputE4 getEditorInput() {
+        return input;
+    }
+
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputDataChangeBehaviourE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputDataChangeBehaviourE4.java
new file mode 100644
index 000000000..5f204279e
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputDataChangeBehaviourE4.java
@@ -0,0 +1,36 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.e4;
+
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.model.AbstractDataChangeBehaviour;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class TaxonEditorInputDataChangeBehaviourE4 extends
+		AbstractDataChangeBehaviour {
+
+	private TaxonEditorInputE4 source;
+
+	public TaxonEditorInputDataChangeBehaviourE4(TaxonEditorInputE4 taxonEditorInput) {
+		source = taxonEditorInput;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void reactOnDataChange(CdmDataChangeMap events) {
+		source.update(events);
+
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputE4.java
new file mode 100644
index 000000000..8527ebfa6
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputE4.java
@@ -0,0 +1,377 @@
+/**
+ * Copyright (C) 2007 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+
+package eu.etaxonomy.taxeditor.editor.e4;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IPersistableElement;
+
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.api.service.IClassificationService;
+import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
+import eu.etaxonomy.cdm.api.service.ITaxonService;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.editor.CdmEntitySessionInput;
+import eu.etaxonomy.taxeditor.editor.ChooseFromMultipleTaxonNodesDialog;
+import eu.etaxonomy.taxeditor.editor.TaxonEditorInputFactory;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.model.DataChangeBridge;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
+import eu.etaxonomy.taxeditor.store.CdmStore;
+
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class TaxonEditorInputE4  extends CdmEntitySessionInput implements IEditorInput, IConversationEnabled, IPersistableElement {
+
+    private static final String INCORRECT_STATE = Messages.TaxonEditorInput_INCORRECT_STATE;
+
+    private final ConversationHolder conversation;
+
+    private TaxonNode taxonNode;
+
+    private TaxonEditorInputDataChangeBehaviourE4 dataChangeBehavior;
+
+    private TaxonBase initiallySelectedTaxonBase;
+
+    private enum CdmType {
+        TAXON_NODE,
+        TAXON_BASE,
+        PARENT_TAXON_NODE
+    }
+
+    private TaxonEditorInputE4(UUID uuid, CdmType type) {
+        super(true);
+        this.conversation = CdmStore.createConversation();
+        switch(type) {
+        case PARENT_TAXON_NODE:
+            initForParentTaxonNode(uuid);
+            break;
+        case TAXON_BASE:
+            initForTaxonBase(uuid);
+            break;
+        case TAXON_NODE:
+            initForTaxonNode(uuid);
+            break;
+        }
+    }
+
+    private void init(TaxonNode taxonNode) {
+        this.taxonNode = taxonNode;
+    }
+
+
+    private void initForTaxonNode(UUID taxonNodeUuid) {
+
+
+        TaxonNode taxonNode = CdmStore.getService(ITaxonNodeService.class).load(taxonNodeUuid, getTaxonNodePropertyPaths());
+
+        if(taxonNode == null){
+            MessagingUtils.warningDialog(Messages.TaxonEditorInput_NOT_IMPLEMENTED, TaxonEditorInputE4.class, Messages.TaxonEditorInput_NOT_IMPLEMENTED_MESSAGE);
+        }
+        init(taxonNode);
+
+    }
+
+    private void initForTaxonBase(UUID taxonBaseUuid) {
+        TaxonBase taxonBase = CdmStore.getService(ITaxonService.class).load(taxonBaseUuid, getTaxonBasePropertyPaths());
+        if (taxonBase != null){
+            if(taxonBase.isInstanceOf(Taxon.class)){
+                Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
+
+                if (taxon.getTaxonNodes().size() == 0 && taxon.isMisapplication()){
+                    // TODO get accepted taxon
+                    MessagingUtils.info(Messages.TaxonEditorInput_OPEN_MISSAPPLIED_NAME);
+
+                    Set<Taxon> acceptedTaxa = new HashSet<Taxon>();
+                    Set<TaxonRelationship> relations = taxon.getRelationsFromThisTaxon();
+                    for(TaxonRelationship relation : relations){
+                        if(relation.getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
+                            acceptedTaxa.add(relation.getToTaxon());
+                        }
+                    }
+                    setInputForMultipleTaxa(conversation, acceptedTaxa);
+
+                }else{
+                    setInputForMultipleNodes(conversation, taxon.getTaxonNodes());
+                }
+            }else if(taxonBase instanceof Synonym){
+                Synonym synonym = (Synonym) taxonBase;
+
+                Set<Taxon> taxa = new HashSet<>();
+                Taxon taxon = synonym.getAcceptedTaxon();
+                if (taxon != null){
+                	taxa.add(taxon);
+                }
+                setInputForMultipleTaxa(conversation, taxa);
+            }
+        }
+    }
+
+
+    private void initForParentTaxonNode(UUID parentNodeUuid){
+
+
+        TaxonName name = PreferencesUtil.getPreferredNomenclaturalCode().getNewTaxonNameInstance(null);
+        ITaxonTreeNode parentNode = CdmStore.getService(IClassificationService.class).getTreeNodeByUuid(parentNodeUuid);
+
+        Taxon newTaxon = Taxon.NewInstance(name, parentNode.getReference());
+        TaxonNode newTaxonNode = parentNode.addChildTaxon(newTaxon, parentNode.getReference(), parentNode.getMicroReference());
+
+        // add the new taxon to the editors persistence context
+        UUID newTaxonNodeUuid = CdmStore.getService(ITaxonNodeService.class).save(newTaxonNode).getUuid();
+
+        initForTaxonNode(newTaxonNodeUuid);
+    }
+
+    private void setInputForMultipleNodes(ConversationHolder conversation, Set<TaxonNode> taxonNodes){
+        if(taxonNodes.size() == 1){
+            TaxonNode taxonNode = taxonNodes.iterator().next();
+            init(taxonNode);
+        }else if(taxonNodes.size() > 1){
+            TaxonNode taxonNode = ChooseFromMultipleTaxonNodesDialog.choose(taxonNodes);
+            if(taxonNode != null){
+                init(taxonNode);
+            }
+        } else if (taxonNodes.size() == 0) {
+            // this is an undesired state
+            MessagingUtils.warningDialog(INCORRECT_STATE,TaxonEditorInputE4.class,Messages.TaxonEditorInput_TAXON_NOT_IN_CLASSIFICATION);
+        }
+    }
+
+    private void setInputForMultipleTaxa(ConversationHolder conversation, Set<Taxon> taxa){
+        if(taxa.size() == 1){
+            Taxon taxon = taxa.iterator().next();
+            Set<TaxonNode> nodes = taxon.getTaxonNodes();
+            setInputForMultipleNodes(conversation, nodes);
+        }else if(taxa.size() > 1){
+            Set<TaxonNode> taxonNodes = new HashSet<TaxonNode>();
+            for ( Taxon taxon : taxa ){
+                taxonNodes.addAll(taxon.getTaxonNodes());
+            }
+            setInputForMultipleNodes(conversation, taxonNodes);
+        }else if(taxa.size() == 0){
+            // this is an undesired state
+            MessagingUtils.warningDialog(INCORRECT_STATE, TaxonEditorInputE4.class, Messages.TaxonEditorInput_NO_ACCEPTED_TAXON_PRESENT);
+        }
+    }
+
+    public static TaxonEditorInputE4 NewInstance(UUID taxonNodeUuid) throws Exception {
+        return new TaxonEditorInputE4(taxonNodeUuid, CdmType.TAXON_NODE);
+
+    }
+
+    public static TaxonEditorInputE4 NewInstanceFromTaxonBase(UUID taxonBaseUuid){
+        return new TaxonEditorInputE4(taxonBaseUuid, CdmType.TAXON_BASE);
+    }
+
+
+    public static TaxonEditorInputE4 NewEmptyInstance(UUID parentNodeUuid){
+        return new TaxonEditorInputE4(parentNodeUuid, CdmType.PARENT_TAXON_NODE);
+    }
+
+    @Override
+    public boolean exists() {
+        return taxonNode != null;
+    }
+
+    @Override
+    public ImageDescriptor getImageDescriptor() {
+        return null;
+    }
+
+    @Override
+    public String getName() {
+        if(getTaxon() == null){
+            return null;
+        }
+        TaxonName name = getTaxon().getName();
+        if (name == null || name.getTitleCache() == null) {
+            return Messages.TaxonEditorInput_NEW_TAXON;
+        } else {
+            return name.getTitleCache();
+        }
+    }
+
+    @Override
+    public IPersistableElement getPersistable() {
+        return null;
+    }
+
+    @Override
+    public String getToolTipText() {
+        return getName();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object getAdapter(Class adapter) {
+
+        if (adapter == Taxon.class) {
+            return getTaxon();
+        }
+
+        if (adapter == TaxonNode.class) {
+            return taxonNode;
+        }
+
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Overrides equals to ensure that a taxon can only be edited by
+     * one editor at a time.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (TaxonEditorInputE4.class.equals(obj.getClass())
+                && getTaxon() != null
+                && getTaxon().equals(((TaxonEditorInputE4) obj).getTaxon())) {
+            if (((TaxonEditorInputE4) obj).getInitiallySelectedTaxonBase() != null){
+                setInitiallySelectedTaxonBase(((TaxonEditorInputE4) obj).getInitiallySelectedTaxonBase());
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public Taxon getTaxon(){
+        Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon(), Taxon.class);
+        return taxon;
+    }
+
+    public TaxonNode getTaxonNode() {
+        return taxonNode;
+    }
+
+    @Override
+    public ConversationHolder getConversationHolder() {
+        return conversation;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void update(CdmDataChangeMap events) {
+        if(dataChangeBehavior == null){
+            dataChangeBehavior = new TaxonEditorInputDataChangeBehaviourE4(this);
+        }
+
+        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
+    }
+
+    @Override
+    public String getFactoryId() {
+        return TaxonEditorInputFactory.getFactoryId();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void saveState(IMemento memento) {
+        TaxonEditorInputFactoryE4.saveState(memento, this);
+    }
+
+
+    public void setInitiallySelectedTaxonBase(TaxonBase taxonBase) {
+        this.initiallySelectedTaxonBase = taxonBase;
+    }
+
+    public TaxonBase getInitiallySelectedTaxonBase() {
+        return initiallySelectedTaxonBase;
+    }
+
+    @Override
+    public List<TaxonNode> getRootEntities() {
+        return Arrays.asList(taxonNode);
+    }
+
+    @Override
+    public void merge() {
+       CdmStore.getService(ITaxonNodeService.class).merge(taxonNode, true);
+
+    }
+
+    @Override
+    public Map<Object, List<String>> getPropertyPathsMap() {
+        return null;
+    }
+
+    private List<String> getTaxonNodePropertyPaths() {
+        List<String> taxonNodePropertyPaths = new ArrayList<String>();
+        for(String propertyPath : getTaxonBasePropertyPaths()) {
+            taxonNodePropertyPaths.add("taxon." + propertyPath); //$NON-NLS-1$
+        }
+        return taxonNodePropertyPaths;
+    }
+
+    private List<String> getTaxonBasePropertyPaths() {
+        List<String> taxonBasePropertyPaths = Arrays.asList(new String[] {
+                "sec", //$NON-NLS-1$
+                "createdBy", //$NON-NLS-1$
+                "updatedBy", //$NON-NLS-1$
+                "annotations", //$NON-NLS-1$
+                "markers", //$NON-NLS-1$
+                "credits", //$NON-NLS-1$
+                "extensions", //$NON-NLS-1$
+                "rights", //$NON-NLS-1$
+                "sources", //$NON-NLS-1$
+                "descriptions", //$NON-NLS-1$
+                "relationsToThisTaxon", //$NON-NLS-1$
+                "relationsFromThisTaxon", //$NON-NLS-1$
+                "taxonNodes", //$NON-NLS-1$
+                "descriptions.descriptionElements.feature", //$NON-NLS-1$
+                "descriptions.descriptionElements.area", //$NON-NLS-1$
+                "descriptions.descriptionElements.status", //$NON-NLS-1$
+                "descriptions.markers", //$NON-NLS-1$
+                "name.descriptions", //$NON-NLS-1$
+                "name.typeDesignations", //$NON-NLS-1$
+                "name.status", //$NON-NLS-1$
+                "name.nomenclaturalReference.inReference", //$NON-NLS-1$
+                "name.taxonBases.taxonNodes", //$NON-NLS-1$
+                "name.relationsFromThisName", //$NON-NLS-1$
+                "name.relationsToThisName", //$NON-NLS-1$
+                "name.homotypicalGroup.typifiedNames.taxonBases.synonymRelations.synonym.name.status", //$NON-NLS-1$
+                "name.homotypicalGroup.typifiedNames.relationsToThisName.fromName", //$NON-NLS-1$
+                "synonymRelations.synonym.name.status.type", //$NON-NLS-1$
+                "synonymRelations.synonym.name.relationsToThisName.fromName", //$NON-NLS-1$
+                "synonymRelations.synonym.name.nomenclaturalReference.inReference.authorship", //$NON-NLS-1$
+                "synonymRelations.synonym.name.nomenclaturalReference.authorship", //$NON-NLS-1$
+                "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.synonymRelations" //$NON-NLS-1$
+        });
+
+        return taxonBasePropertyPaths;
+    }
+
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputFactoryE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputFactoryE4.java
new file mode 100644
index 000000000..aaf3c5fd6
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/e4/TaxonEditorInputFactoryE4.java
@@ -0,0 +1,82 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.e4;
+
+import java.util.UUID;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ui.IElementFactory;
+import org.eclipse.ui.IMemento;
+
+import eu.etaxonomy.cdm.api.service.IClassificationService;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.store.CdmStore;
+
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class TaxonEditorInputFactoryE4 implements IElementFactory {
+
+    /**
+     * Factory id. The workbench plug-in registers a factory by this name
+     * with the "org.eclipse.ui.elementFactories" extension point.
+     */
+    private static final String ID_FACTORY = "eu.etaxonomy.taxeditor.editor.name.taxonEditorInputFactory"; //$NON-NLS-1$
+
+    /**
+     * Tag for the IFile.fullPath of the file resource.
+     */
+    private static final String TAXON_NODE_UUID = "uuid"; //$NON-NLS-1$
+
+	/** {@inheritDoc} */
+	@Override
+    public IAdaptable createElement(IMemento memento) {
+        // Get the uuid
+        String taxonNodeUuid = memento.getString(TAXON_NODE_UUID);
+        if(! CdmStore.isActive()){
+        	return null;
+        }
+        if (taxonNodeUuid == null || CdmStore.getService(IClassificationService.class).getTaxonNodeByUuid(UUID.fromString(taxonNodeUuid)) == null) {
+        	MessagingUtils.warn(this.getClass(), Messages.TaxonEditorInputFactory_NOT_FOUND_TAXON + taxonNodeUuid);
+        	return null;
+        }
+        try {
+			return TaxonEditorInputE4.NewInstance(UUID.fromString(taxonNodeUuid));
+		} catch (Exception e) {
+			MessagingUtils.warningDialog(Messages.TaxonEditorInputFactory_COULD_NOT_CREATE, TaxonEditorInputFactoryE4.class, e.getMessage());
+		}
+		return null;
+	}
+
+    /**
+     * Returns the element factory id for this class.
+     *
+     * @return the element factory id
+     */
+    public static String getFactoryId() {
+        return ID_FACTORY;
+    }
+
+    /**
+     * Saves the state of the given file editor input into the given memento.
+     *
+     * @param memento the storage area for element state
+     * @param input the file editor input
+     */
+    public static void saveState(IMemento memento, TaxonEditorInputE4 input) {
+    	String uuid = input.getTaxonNode().getUuid().toString();
+        memento.putString(TAXON_NODE_UUID, uuid);
+    }
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/IDropTargetableE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/IDropTargetableE4.java
new file mode 100644
index 000000000..11b44a17f
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/IDropTargetableE4.java
@@ -0,0 +1,25 @@
+/**
+ *
+ */
+package eu.etaxonomy.taxeditor.editor.name.e4;
+
+import org.eclipse.swt.widgets.Composite;
+
+import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public interface IDropTargetableE4 extends IPostOperationEnabled {
+
+	public Composite getControl();
+
+	public TaxonNameEditorE4 getEditor();
+
+	public void dragEntered();
+
+	public void dragLeft();
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/TaxonNameEditorE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/TaxonNameEditorE4.java
new file mode 100644
index 000000000..b832c5fa5
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/TaxonNameEditorE4.java
@@ -0,0 +1,591 @@
+/**
+ * Copyright (C) 2007 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+
+package eu.etaxonomy.taxeditor.editor.name.e4;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.services.EMenuService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.ISelectionService;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.ManagedForm;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.editor.ISecuredEditor;
+import eu.etaxonomy.taxeditor.editor.e4.TaxonEditorInputE4;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.AbstractGroupE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.AbstractGroupedContainerE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.AcceptedGroupE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.AcceptedNameContainerE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.ContainerFactoryE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.HomotypicalSynonymGroupE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.container.MisappliedGroupE4;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
+import eu.etaxonomy.taxeditor.model.IPartChangeListener;
+import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
+import eu.etaxonomy.taxeditor.model.TaxeditorPartService;
+import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
+import eu.etaxonomy.taxeditor.preference.Resources;
+import eu.etaxonomy.taxeditor.security.RequiredPermissions;
+import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
+import eu.etaxonomy.taxeditor.store.CdmStore;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class TaxonNameEditorE4 implements
+		IConversationEnabled, IDirtyMarkable,
+		IPartContentHasDetails, IPartChangeListener,
+		ISelectionListener, ISecuredEditor, IPostOperationEnabled {
+
+	private Taxon taxon;
+
+	private ManagedForm managedForm;
+	private ScrolledForm scrolledForm;
+	private Composite parent;
+	private ISelectionProvider simpleSelectionProvider;
+
+	private TaxonBase selection;
+
+	private ConversationHolder conversation;
+
+	private MenuManager menuManager;
+	private Menu menu;
+
+	private AcceptedGroupE4 acceptedGroup;
+	private List<HomotypicalSynonymGroupE4> heterotypicSynonymGroups = new ArrayList<>();
+	private MisappliedGroupE4 misappliedGroup;
+
+	private ISelectionService selectionService;
+
+	private TaxonBase objectAffectedByLastOperation;
+
+	private ICdmEntitySession cdmEntitySession;
+
+	@Inject
+	private ESelectionService selService;
+
+	@Inject
+	private MDirtyable dirty;
+
+	private ISelectionChangedListener selectionChangedListener;
+
+    private TaxonEditorInputE4 input;
+
+	@Inject
+	public TaxonNameEditorE4() {
+	}
+
+
+	@PostConstruct
+    public void createPartControl(Composite parent, EMenuService menuService) {
+        if (CdmStore.isActive()){
+            if(conversation == null){
+                conversation = CdmStore.createConversation();
+            }
+        }
+        else{
+            return;
+        }
+
+		createManagedForm(parent);
+
+		//propagate selection
+        selectionChangedListener = (event -> selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event)));
+        //FIXME E4 migrate
+//        viewer.addSelectionChangedListener(selectionChangedListener);
+
+        //create context menu
+        menuService.registerContextMenu(managedForm, "eu.etaxonomy.taxeditor.editor.popupmenu.nameeditor");
+
+		TaxeditorPartService.getInstance().addListener(
+				TaxeditorPartService.PART_ACTIVATED, this);
+
+	}
+
+	protected void createManagedForm(Composite composite) {
+
+		managedForm = new ManagedForm(composite) {
+
+			@Override
+			public void dirtyStateChanged() {
+			    dirty.setDirty(true);
+			    //FIXME E4 migrate
+//				firePropertyChange(PROP_DIRTY);
+			}
+
+			@Override
+			public boolean setInput(Object input) {
+				if (input instanceof AbstractGroupedContainer) {
+					selection = ((AbstractGroupedContainer) input).getData();
+
+			        selectionChangedListener = (event -> selService.setSelection(new StructuredSelection(selection)));
+				}else if(input == null){
+					selection = null;
+                    selectionChangedListener = (event -> selService.setSelection(new StructuredSelection()));
+				}
+
+
+				return super.setInput(input);
+			}
+		};
+
+		scrolledForm = managedForm.getForm();
+		parent = scrolledForm.getBody();
+
+		parent.setData(taxon);
+
+		TableWrapLayout layout = new TableWrapLayout();
+		layout.leftMargin = 0;
+		layout.rightMargin = 0;
+		layout.topMargin = 0;
+		layout.bottomMargin = 0;
+
+		layout.verticalSpacing = 0;
+		layout.horizontalSpacing = 0;
+
+		parent.setLayout(layout);
+		parent.setBackground(AbstractUtility
+				.getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
+	}
+
+	public void createOrUpdateNameComposites() {
+		ContainerFactoryE4.createOrUpdateAcceptedTaxonsHomotypicGroup(this);
+		ContainerFactoryE4.createOrUpdateHeterotypicSynonymyGroups(this);
+		ContainerFactoryE4.createOrUpdateMisapplicationsGroup(this);
+
+
+		// Redraw composite
+		managedForm.reflow(true);
+	}
+
+	public Taxon getTaxon() {
+		return HibernateProxyHelper.deproxy(taxon);
+	}
+
+	public void setDirty() {
+		managedForm.dirtyStateChanged();
+	}
+
+	@Focus
+	public void setFocus() {
+	    if(input!=null){
+	        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().setFocus();
+	        if (getSelectedContainer() == null) {
+	            throw new IllegalStateException(
+	                    Messages.TaxonNameEditor_THERE_SHOULD_ALWAYS_BE);
+	        }
+	        getSelectedContainer().setSelected();
+
+	        // check permissions
+	        boolean doEnable = permissionsSatisfied();
+	        managedForm.getForm().setEnabled(doEnable);
+	    }
+	}
+
+	@Override
+	public boolean permissionsSatisfied() {
+		TaxonNode taxonNode = input.getTaxonNode();
+		boolean doEnable = CdmStore.currentAuthentiationHasPermission(taxonNode, RequiredPermissions.TAXONNODE_EDIT);
+		return doEnable;
+	}
+
+	@Override
+    public ConversationHolder getConversationHolder() {
+		return conversation;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void update(CdmDataChangeMap events) {
+		// redraw();
+	}
+
+	/**
+	 * Redraws this editor return true on success
+	 *
+	 * @return a boolean.
+	 */
+    public boolean redraw() {
+		return redraw(true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * Redraws the editor controls
+	 */
+    public boolean redraw(boolean focus) {
+
+		createOrUpdateNameComposites();
+
+		if (focus) {
+			setFocus();
+		}
+
+		return true;
+	}
+
+	@Override
+    public boolean postOperation(CdmBase objectAffectedByOperation) {
+
+		changed(objectAffectedByOperation);
+
+		redraw(false);
+
+		if (objectAffectedByOperation instanceof TaxonBase) {
+			objectAffectedByLastOperation = (TaxonBase) objectAffectedByOperation;
+		}
+
+		return true;
+	}
+
+	public ManagedForm getManagedForm() {
+		return managedForm;
+	}
+
+	public Menu getMenu() {
+		if (menu == null || menu.isDisposed()) {
+			// Creating the menu because it was either not initialised or
+			// disposed while refreshing the editor
+			menu = menuManager.createContextMenu(parent);
+		}
+		return menu;
+	}
+
+	/**
+	 * <p>
+	 * checkForEmptyNames
+	 * </p>
+	 *
+	 * @return true if there are empty names
+	 */
+	public boolean checkForEmptyNames() {
+		for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
+			if (container.getName() == null
+					|| StringUtils.isEmpty(container.getName().getTitleCache())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public Set<AbstractGroupedContainerE4> getEmptyContainers() {
+		Set<AbstractGroupedContainerE4> containersWithEmptyNames = new HashSet<>();
+
+		for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
+			if (container.getName() == null
+					|| StringUtils.isEmpty(container.getName().getTitleCache())) {
+				containersWithEmptyNames.add(container);
+			}
+		}
+
+		return containersWithEmptyNames;
+	}
+
+	/** {@inheritDoc} */
+	@Persist
+	public void doSave(IProgressMonitor monitor) {
+
+		monitor.beginTask(Messages.TaxonNameEditor_SAVING_NAMES, getGroupedContainers().size());
+
+		try {
+			// check for empty names
+			for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
+
+				monitor.subTask(Messages.TaxonNameEditor_SAVING_COMPOSITES
+						+ container.getTaxonBase().getTitleCache());
+				container.persistName();
+
+				// In case the progress monitor was canceled throw an exception.
+				if (monitor.isCanceled()) {
+					throw new OperationCanceledException();
+				}
+
+				// Otherwise declare this step as done.
+				monitor.worked(1);
+			}
+		} finally {
+
+			// Stop the progress monitor.
+			monitor.done();
+		}
+
+	}
+
+	public void init(TaxonEditorInputE4 input)
+			throws PartInitException {
+
+		if (!(input != null)) {
+            throw new PartInitException(Messages.TaxonNameEditor_INVALID_INPUT);
+        }
+
+		if (input.getAdapter(Taxon.class) != null) {
+			taxon = CdmBase.deproxy(input.getAdapter(Taxon.class), Taxon.class);
+		} else {
+			throw new PartInitException(Messages.TaxonNameEditor_INVALID_INPUT_TAXON_NULL);
+		}
+
+		this.input = input;
+
+        createOrUpdateNameComposites();
+
+        setFocus();
+	}
+
+
+	public AcceptedNameContainerE4 getAcceptedNameContainer() {
+		return getAcceptedGroup().getAcceptedNameContainer();
+	}
+
+	public HomotypicalSynonymGroupE4 getHomotypicalGroupContainer(
+			HomotypicalGroup homotypicalGroup) {
+		for (HomotypicalSynonymGroupE4 group : getHeterotypicSynonymGroups()) {
+			if (group.getGroup().equals(homotypicalGroup)) {
+				return group;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * getDirtyNames
+	 * </p>
+	 *
+	 * @return a Set containing all composites that have been edited
+	 */
+	public Set<AbstractGroupedContainerE4> getDirtyNames() {
+		Set<AbstractGroupedContainerE4> dirtyNames = new HashSet<>();
+
+		for (AbstractGroupedContainerE4 composite : getGroupedContainers()) {
+			if (composite.isDirty()) {
+				dirtyNames.add(composite);
+			}
+		}
+
+		return dirtyNames;
+	}
+
+	public List<AbstractGroupedContainerE4> getGroupedContainers() {
+		List<AbstractGroupedContainerE4> groupedComposites = new ArrayList<>();
+
+		for (AbstractGroupE4 group : getAllGroups()) {
+			groupedComposites.addAll(group.getGroupedContainers());
+		}
+
+		return groupedComposites;
+	}
+
+	public List<AbstractGroupE4> getAllGroups() {
+		List<AbstractGroupE4> allGroups = new ArrayList<>();
+
+		allGroups.add(getAcceptedGroup());
+
+		heterotypicSynonymGroups = getHeterotypicSynonymGroups();
+
+		if (heterotypicSynonymGroups != null) {
+			allGroups.addAll(heterotypicSynonymGroups);
+		}
+
+		if (misappliedGroup != null) {
+			allGroups.add(misappliedGroup);
+		}
+
+		return allGroups;
+	}
+
+	public boolean isDirty() {
+		return dirty.isDirty();
+	}
+
+	@PreDestroy
+	public void dispose() {
+		conversation.unregisterForDataStoreChanges(this);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+
+	}
+
+	public AbstractGroupedContainerE4 getSelectedContainer() {
+
+		TaxonBase selectedTaxonBase = null;
+
+		if (input.getInitiallySelectedTaxonBase() != null) {
+			selectedTaxonBase = input.getInitiallySelectedTaxonBase();
+		} else {
+			if (selection != null) {
+				selectedTaxonBase = selection;
+			}
+		}
+
+		return (selectedTaxonBase != null) ? getContainer(selectedTaxonBase)
+				: getAcceptedNameContainer();
+	}
+
+	public void setMisapplicationsGroup(MisappliedGroupE4 misappliedGroup) {
+		this.misappliedGroup = misappliedGroup;
+	}
+
+	public FormToolkit getToolkit() {
+		return managedForm.getToolkit();
+	}
+
+	public List<HomotypicalSynonymGroupE4> getHeterotypicSynonymGroups() {
+		return heterotypicSynonymGroups;
+	}
+
+	public void addHeterotypicSynonymGroup(HomotypicalSynonymGroupE4 group) {
+		heterotypicSynonymGroups.add(group);
+	}
+
+	public AcceptedGroupE4 getAcceptedGroup() {
+		return acceptedGroup;
+	}
+
+	public void setAcceptedGroup(AcceptedGroupE4 acceptedGroup) {
+		this.acceptedGroup = acceptedGroup;
+	}
+
+	public MisappliedGroupE4 getMisappliedGroup() {
+		return misappliedGroup;
+	}
+
+	public boolean isActive() {
+		return this.equals(AbstractUtility.getActiveE4Part());
+	}
+
+    @Override
+    public boolean onComplete() {
+		getContainer(objectAffectedByLastOperation).setSelected();
+		return true;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void partChanged(Integer eventType, IWorkbenchPartReference partRef) {
+		if (!partRef.getPart(false).equals(this)) {
+			// getSelectedObject().colorSelected(AbstractGroupedContainer.SELECTED_NO_FOCUS);
+		}
+	}
+
+	public void removeGroup(AbstractGroupE4 group) {
+		if (group != null) {
+			group.dispose();
+
+			//if (heterotypicSynonymGroups != null) {
+			heterotypicSynonymGroups.remove(group);
+			//}
+		}
+	}
+
+	public AbstractGroupedContainerE4 getContainer(TaxonBase taxonBase) {
+		List<AbstractGroupedContainerE4> groupedContainers = getGroupedContainers();
+		for (AbstractGroupedContainerE4 container : groupedContainers) {
+			if (container.getData().equals(taxonBase)
+					&& container.getNameViewer().getTextWidget() != null) {
+				return container;
+			}
+		}
+		return getAcceptedNameContainer();
+	}
+
+    public void setOnError() {
+		Color disabledColor =  AbstractUtility.getColor(Resources.COLOR_EDITOR_ERROR);
+		setEnabled(false, disabledColor);
+	}
+
+	public void setDisabled(){
+		Color disabledColor =  AbstractUtility.getColor(Resources.COLOR_TEXT_DISABLED_BACKGROUND);
+		setEnabled(false, disabledColor);
+	}
+
+	protected void setEnabled(boolean enabled, Color background) {
+
+		for(AbstractGroupedContainerE4 groupedContainer : getGroupedContainers()){
+			groupedContainer.setEnabled(enabled);
+		}
+
+		// send an empty selection to the current provider - TODO only on error ???
+		if (!enabled) {
+			getManagedForm().setInput(null);
+
+			for (AbstractGroupedContainerE4 groupedContainer : getGroupedContainers()) {
+				groupedContainer.setBackground(background);
+			}
+		}
+		managedForm.getForm().setBackground(background);
+	}
+
+    @Override
+    public void changed(Object element) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void forceDirty() {
+        setDirty();
+    }
+
+
+    public IUndoContext getUndoContext() {
+        //FIXME E4 is this needed
+        return null;
+    }
+
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractGroupE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractGroupE4.java
new file mode 100644
index 000000000..da149bce1
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractGroupE4.java
@@ -0,0 +1,193 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.taxeditor.editor.CdmDataTransfer;
+import eu.etaxonomy.taxeditor.editor.name.dnd.NameEditorDropTargetEffect;
+import eu.etaxonomy.taxeditor.editor.name.e4.IDropTargetableE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.dnd.NameEditorDropTargetListenerE4;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public abstract class AbstractGroupE4 implements IDropTargetableE4{
+
+	private Composite control;
+
+	private final List<AbstractGroupedContainerE4> groupedContainers = new ArrayList<>();
+
+	protected TaxonNameEditorE4 editor;
+
+	private DropTarget target;
+	private DropTargetListener dropListener;
+
+	public AbstractGroupE4(TaxonNameEditorE4 editor){
+		this.editor = editor;
+	}
+
+	protected void createContent(){
+		createControl();
+
+		createContainers();
+
+		// Drop functionality
+		this.setDroppable(true);
+
+		editor.getManagedForm().reflow(true);
+	}
+
+	protected void createControl() {
+		control = editor.getToolkit().createComposite(editor.getManagedForm().getForm());
+
+		control.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
+		TableWrapLayout layout = new TableWrapLayout();
+
+		layout.topMargin = 0;
+		layout.rightMargin = 0;
+		layout.bottomMargin = 1;
+		layout.leftMargin = 0;
+
+		layout.verticalSpacing = 0;
+		layout.horizontalSpacing = 0;
+		control.setLayout(layout);
+
+		control.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
+	}
+
+	public void add(AbstractGroupedContainerE4 groupedContainer){
+		groupedContainers.add(groupedContainer);
+		groupedContainer.setGroup(this);
+	}
+
+	public void remove(AbstractGroupedContainerE4 groupedContainer){
+		groupedContainer.dispose();
+		groupedContainers.remove(groupedContainer);
+
+		if(!(this instanceof AcceptedGroupE4) && groupedContainers.isEmpty()){
+			getEditor().removeGroup(this);
+		}
+	}
+
+	public List<AbstractGroupedContainerE4> getGroupedContainers(){
+		return groupedContainers;
+	}
+
+
+	public void setDroppable(boolean droppable) {
+		if (droppable) {
+			Transfer[] types = new Transfer[] {CdmDataTransfer.getInstance()};
+			int operations = DND.DROP_MOVE;
+			target = new DropTarget(control, operations);
+			target.setTransfer(types);
+			dropListener = new NameEditorDropTargetListenerE4(this);
+			target.addDropListener(dropListener);
+
+			target.setDropTargetEffect(new NameEditorDropTargetEffect(control));
+
+		} else {
+			if (dropListener != null) {
+				target.removeDropListener(dropListener);
+			}
+		}
+	}
+
+	@Override
+    public TaxonNameEditorE4 getEditor() {
+		return editor;
+	}
+
+	@Override
+    public void dragEntered() {
+		Color color = AbstractUtility.getColor(Resources.COLOR_DRAG_ENTER);
+
+		for(AbstractGroupedContainerE4 container : groupedContainers){
+			container.setBackground(color);
+		}
+	}
+
+	@Override
+    public void dragLeft() {
+		for(AbstractGroupedContainerE4 container : groupedContainers){
+			container.restoreColor();
+		}
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public boolean postOperation(CdmBase objectAffectedByOperation) {
+		editor.changed(objectAffectedByOperation);
+		redraw();
+		return true;
+	}
+
+	public void redraw(){
+		emptyGroup();
+		createContainers();
+	}
+
+	protected abstract void createContainers();
+
+	@Override
+	public Composite getControl() {
+		return control;
+	}
+
+	@Override
+	public boolean onComplete() {
+		return true;
+	}
+
+	public void dispose(){
+		if(getControl() != null){
+			for(AbstractGroupedContainerE4 container : getGroupedContainers()){
+				container.dispose();
+			}
+			getControl().setMenu(null);
+			getControl().dispose();
+		}
+	}
+
+	public void setMenu(Menu menu) {
+		getControl().setMenu(menu);
+		for(AbstractGroupedContainerE4 container : getGroupedContainers()){
+			container.setMenu(menu);
+		}
+
+	}
+
+	protected void emptyGroup(){
+		for(AbstractGroupedContainerE4 container : groupedContainers){
+			container.dispose();
+		}
+		groupedContainers.clear();
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractGroupedContainerE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractGroupedContainerE4.java
new file mode 100755
index 000000000..6bafd9af1
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractGroupedContainerE4.java
@@ -0,0 +1,903 @@
+/**
+ * Copyright (C) 2007 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.window.DefaultToolTip;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.forms.IFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
+import eu.etaxonomy.taxeditor.editor.CdmDataTransfer;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.editor.name.container.EditorAnnotation;
+import eu.etaxonomy.taxeditor.editor.name.container.EditorAnnotation.EditorAnnotationType;
+import eu.etaxonomy.taxeditor.editor.name.container.IContainerConstants;
+import eu.etaxonomy.taxeditor.editor.name.container.LineBreakListener;
+import eu.etaxonomy.taxeditor.editor.name.container.LineWrapSupport;
+import eu.etaxonomy.taxeditor.editor.name.container.NameViewer;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+import eu.etaxonomy.taxeditor.editor.name.operation.CreateSynonymInNewGroupOperation;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.model.IElementHasDetails;
+import eu.etaxonomy.taxeditor.model.NameHelper;
+import eu.etaxonomy.taxeditor.model.TextHelper;
+import eu.etaxonomy.taxeditor.parser.ParseHandler;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+/**
+ * Formats <code>GroupedComposite</code> with cosmetic and layout properties
+ * specific to the Editor. This should be used to maintain a consistent look and
+ * feel for all Editor freetext area components, such as
+ * DescriptionElementComposite.
+ * <p>
+ * Requires an <code>IManagedForm</code>, whose <code>input</code> is set to the
+ * contents of {@link #getData()} when the <code>GroupedComposite</code> gets
+ * focus, i.e. to populate the property sheet with the data.
+ * </p>
+ * <p>
+ * The <code>IManagedForm</code> is also required to have a <code>Taxon</code>
+ * in its own <code>getData()</code>.
+ * </p>
+ * <p>
+ * The <code>IManagedForm</code> can also used for drawing borders by calling
+ * the method <code>createBorderSupport()</code>.
+ * </p>
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ * @param <T>
+ */
+abstract public class AbstractGroupedContainerE4<T extends TaxonBase> implements
+		IFormPart, IContainerConstants, IElementHasDetails {
+
+	protected ParseHandler parseHandler;
+
+	private FocusListener nameCompositeFocusListener;
+	private ModifyListener nameCompositeModifyListener;
+
+	protected NameViewer nameViewer;
+
+	private AbstractGroupE4 group;
+
+	private Label nonEditableInfoLabel;
+	private DefaultToolTip nonEditableInfoHover;
+
+	private static AbstractGroupedContainerE4 selection;
+
+	private FocusListener focusListener;
+	private LineBreakListener lineBreakListener;
+
+	private int cursorPosition;
+
+	protected Composite control;
+
+	private Color backgroundColor;
+	private boolean isDirty;
+
+	public AbstractGroupedContainerE4(T taxonBase) {
+		setData(taxonBase);
+		parseHandler = ParseHandler.NewInstance(taxonBase.getName());
+	}
+
+	public void createContent() {
+		createControl();
+
+		createTextViewer();
+		createLineWrapSupport();
+		createLineBreakListener();
+
+		//FIXME E4 this has to be done in fragment
+//		setMenu(getEditor().getMenu());
+
+		setDraggableControl(new Control[] { getControl(),
+				getNameViewer().getRulerControl() });
+
+		createEmptyViewerPrompt(EMPTY_NAME_PROMPT);
+
+		initializeComposite();
+
+		createListener();
+
+		enableFreeText();
+	}
+
+	protected void createListener() {
+		nameCompositeModifyListener = new ModifyListener() {
+
+			@Override
+            public void modifyText(ModifyEvent e) {
+				// mark the composite dirty
+				setDirty(true);
+				// parse the text
+				String text = nameViewer.getTextWidget().getText();
+
+				TaxonName name = (TaxonName)parseHandler.parse(text);
+				getTaxonBase().setName(name);
+				getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
+
+				// show errors resulting from parsing
+				calculateAnnotations();
+				// store the position of the cursor
+				storeCursor();
+				// notify selection listener
+				setDelayedSelection();
+			}
+		};
+		nameCompositeFocusListener = new FocusAdapter() {
+
+			@Override
+			public void focusLost(FocusEvent e) {
+				super.focusLost(e);
+
+				persistName();
+			}
+		};
+
+		addListener();
+	}
+
+	protected void addListener() {
+		getNameViewer().getTextWidget().addModifyListener(
+				nameCompositeModifyListener);
+		getNameViewer().getTextWidget().addFocusListener(
+				nameCompositeFocusListener);
+	}
+
+	protected void removeListener() {
+		getNameViewer().getTextWidget().removeModifyListener(
+				nameCompositeModifyListener);
+		getNameViewer().getTextWidget().removeFocusListener(
+				nameCompositeFocusListener);
+	}
+
+	/**
+	 * Initialize the composite specific code
+	 */
+	protected abstract void initializeComposite();
+
+	protected String getEmptyTextPrompt() {
+		return EMPTY_NAME_PROMPT;
+	}
+
+	protected void initTextViewer() {
+
+		updateIndent();
+
+		updateIcon();
+
+		String text = NameHelper.getDisplayNameWithRef(getData());
+
+		if (text.length() == 0) {
+			initEmptyText();
+		} else {
+			getNameViewer().setText(text);
+			placeCursor();
+		}
+		calculateAnnotations();
+	}
+
+	synchronized protected void calculateAnnotations() {
+		getNameViewer().clearAnnotations();
+		showAnnotations();
+	}
+
+	public void showAnnotations() {
+
+		if (getName() != null && getName().hasProblem()) {
+			showParsingProblems();
+		}
+
+		if (!isNameParsable()) {
+			getNameViewer()
+					.addAnnotation(
+							new EditorAnnotation(EditorAnnotationType.WARNING,
+									0,
+									Messages.AbstractGroupedContainer_EDIT_IN_DETAILS_VIEW));
+		}
+
+		if (isNameUsedMultipleTimes()) {
+			getNameViewer().addAnnotation(
+					new EditorAnnotation(EditorAnnotationType.WARNING, 0,
+							Messages.AbstractGroupedContainer_MULTIPLE_USE));
+		}
+
+	}
+
+	private void showParsingProblems() {
+		TaxonName name = getName();
+		if (name == null){
+			return;
+		}
+
+		List<ParserProblem> parsingProblems = name.getParsingProblems();
+
+		for (ParserProblem problem : parsingProblems) {
+			getNameViewer().addAnnotation(new EditorAnnotation(problem),
+					getParsingProblemPosition());
+		}
+	}
+
+	private Position getParsingProblemPosition() {
+		String text = getNameViewer().getTextWidget().getText();
+
+		if (getName() != null && getName().hasProblem() && text.length() > 0) {
+			int start = getName().getProblemStarts();
+			int length = getName().getProblemEnds() - start;
+
+			if (start == -1 || getName().getProblemEnds() == -1) {
+				return null;
+			}
+
+			// Don't let squigglies try to draw beyond the end of the text
+			if (text.length() < start + length) {
+				length = text.length() - start;
+			}
+			if (length<0){
+				return null;
+			}
+			return new Position(start, length);
+		}
+		return null;
+	}
+
+	protected void handleSplitText(String text) {
+		// Create a synonym in a new homotypic group using text as name
+		TaxonName synonymName = TaxonName.castAndDeproxy(
+				ParseHandler.parseReferencedName(text, null));
+
+		AbstractUtility.executeOperation(new CreateSynonymInNewGroupOperation(
+				Messages.AbstractGroupedContainer_NEW_HETERO_SYNONYM, getEditor().getUndoContext(),
+				getEditor().getTaxon(), synonymName, getEditor()));
+	}
+
+	/**
+	 * Refreshes the display with latest data from the model.
+	 *
+	 * Note: Will not parse the text and not calculate errors!
+	 */
+	@Override
+    public void refresh() {
+		// showNameRelations();
+
+		String text = NameHelper.getDisplayNameWithRef(getTaxonBase());
+
+		if (getNameViewer().getTextWidget() == null) {
+			// we might get here via dnd. Look slike it can be ignored
+			return;
+		}
+
+		if (text.length() == 0) {
+			initEmptyText();
+		} else if (!getNameViewer().getTextWidget().getText().equals(text)) {
+			removeListener();
+			getNameViewer().getTextWidget().setText(text);
+			addListener();
+		}
+
+		updateNonEditableInfo();
+
+		updateIcon();
+		// placeCursor();
+		updateIndent();
+
+		enableFreeText();
+	}
+
+	protected abstract void updateIcon();
+
+	protected abstract void updateIndent();
+
+	protected abstract void updateNonEditableInfo();
+
+	protected void enableFreeText() {
+		setEnabled(isFreetextEditingAllowed());
+	}
+
+	/**
+	 * Checks whether the freetext should be editable based on specific empty
+	 * fields.
+	 *
+	 * @return
+	 */
+	private boolean isFreetextEditingAllowed() {
+		boolean enableFreetext = true;
+
+		enableFreetext |= isNameUsedMultipleTimes();
+		enableFreetext &= isNameParsable();
+
+		return enableFreetext;
+	}
+
+	/**
+	 * Checks whether there are more than one, non-orphaned taxon bases
+	 * attached to the taxon name
+	 *
+	 * @return
+	 */
+	private boolean isNameUsedMultipleTimes() {
+
+		TaxonName name = getName();
+		if (name != null){
+			Set<TaxonBase> taxonBases = name.getTaxonBases();
+			Iterator<TaxonBase> tbItr = taxonBases.iterator();
+			int nonOrphanedTaxonBaseCount = taxonBases.size();
+
+			while(tbItr.hasNext()) {
+				TaxonBase<?> tb = tbItr.next();
+				if(tb.isOrphaned()) {
+					nonOrphanedTaxonBaseCount--;
+				}
+			}
+			if(nonOrphanedTaxonBaseCount > 1) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean isNameParsable() {
+		TaxonName name = getName();
+		if (name == null){
+			return false;
+		}
+
+		boolean isParsable = true;
+		isParsable &= StringUtils.isBlank(name.getAppendedPhrase()); // taxonFieldsEmpty();
+
+		isParsable &= !name.isProtectedAuthorshipCache();
+		isParsable &= !name.isProtectedNameCache();
+
+		return isParsable;
+	}
+
+	/**
+	 * Parse the text and calculate errors
+	 */
+	public void parseAndCalculateAnnotations() {
+		removeListener();
+		String unparsedNameString = getNameViewer().getTextWidget().getText();
+		parseHandler.parse(unparsedNameString);
+		addListener();
+		calculateAnnotations();
+	}
+
+	public T getTaxonBase() {
+		return getData();
+	}
+
+	public TaxonName getName() {
+		return CdmBase.deproxy(getTaxonBase().getName());
+	}
+
+	public void persistName() {
+		if (isDirty()) {
+			getNameViewer().getTextWidget().setEnabled(false);
+			final String unparsedNameString = getNameViewer().getTextWidget()
+					.getText();
+			final TaxonName name = (TaxonName)parseHandler
+					.parseAndResolveDuplicates(unparsedNameString);
+			getTaxonBase().setName(name);
+			getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
+			setDirty(false);
+			getNameViewer().getTextWidget().setEnabled(true);
+		}
+	}
+
+	public AbstractGroupE4 getGroup() {
+		if (group == null) {
+			throw new IllegalStateException("Group shall not be null."); //$NON-NLS-1$
+		}
+		return group;
+	}
+
+	public void remove() {
+		getGroup().remove(this);
+	}
+
+	protected void createControl() {
+		control = getEditor().getToolkit().createComposite(
+				getGroup().getControl());
+
+		control.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
+		TableWrapLayout layout = new TableWrapLayout();
+		layout.leftMargin = 0;
+		layout.rightMargin = 0;
+		layout.topMargin = 5;
+		layout.bottomMargin = 5;
+
+		layout.verticalSpacing = 0;
+		layout.horizontalSpacing = 0;
+
+		control.setLayout(layout);
+
+	}
+
+	protected TaxonNameEditorE4 getEditor() {
+		return getGroup().getEditor();
+	}
+
+	public Composite getControl() {
+		return control;
+	}
+
+	protected void createLineWrapSupport() {
+		new LineWrapSupport(getNameViewer(), getEditor().getManagedForm());
+	}
+
+	protected void createTextViewer() {
+		nameViewer = new NameViewer(control);
+
+		focusListener = new FocusAdapter() {
+			@Override
+			public void focusGained(FocusEvent e) {
+				if(!enabled){
+					return;
+				}
+				for (AbstractGroupedContainerE4 container : getEditor()
+						.getGroupedContainers()) {
+					container.colorSelected(NOT_SELECTED);
+				}
+				getEditor().getManagedForm().setInput(
+						AbstractGroupedContainerE4.this);
+				placeCursor();
+				colorSelected(SELECTED_FOCUS);
+			}
+		};
+		nameViewer.getTextWidget().addFocusListener(focusListener);
+
+		MouseAdapter mouseListener = new MouseAdapter() {
+			@Override
+			public void mouseDown(MouseEvent e) {
+				storeCursor();
+			}
+		};
+		control.addMouseListener(mouseListener);
+		nameViewer.getRulerControl().addMouseListener(mouseListener);
+		nameViewer.getTextWidget().addMouseListener(mouseListener);
+	}
+
+	public void setIcon(Image icon) {
+		getNameViewer().setIcon(icon);
+	}
+
+	public void setIndent(int indent) {
+		if (control.getLayout() instanceof TableWrapLayout) {
+			TableWrapLayout layout = ((TableWrapLayout) control.getLayout());
+			layout.leftMargin = indent;
+			layout.rightMargin = ACCEPTED_INDENT;
+			control.setLayout(layout);
+			control.layout();
+		} else {
+			throw new RuntimeException(
+					"Couldn't indent - composite's layout must be TableWrapLayout."); //$NON-NLS-1$
+		}
+	}
+
+	public void setSelected() {
+		getNameViewer().getTextWidget().setFocus();
+	}
+
+	public boolean isSelected() {
+		return getEditor().getSelectedContainer() == this;
+	}
+
+	public void colorSelected(int mode) {
+		if (!control.isDisposed()) {
+			String colorString = null;
+
+			switch (mode) {
+			case SELECTED_FOCUS:
+				colorString = Resources.COLOR_CONTROL_SELECTED_FOCUS;
+				break;
+			case SELECTED_NO_FOCUS:
+				colorString = Resources.COLOR_CONTROL_SELECTED;
+				break;
+			default:
+				colorString = Resources.COLOR_COMPOSITE_BACKGROUND;
+			}
+
+			backgroundColor = AbstractUtility.getColor(colorString);
+
+			setBackground(backgroundColor);
+		}
+	}
+
+	protected void setDelayedSelection() {
+		// TODO this might be done better
+		// this is the quickest solution i could come up with and it improves
+		// performance
+		// please reimplement if you know better.
+		selection = this;
+
+		// start timer
+		Display display = Display.getCurrent();
+		Runnable runnable = new Runnable() {
+
+			@Override
+            public void run() {
+				getEditor().getManagedForm().setInput(selection);
+			}
+		};
+		display.timerExec(1000, runnable);
+
+	}
+
+	public void setBackground(Color color) {
+		control.setBackground(color);
+
+		for (Control child : control.getChildren()) {
+			child.setBackground(color);
+		}
+
+		getNameViewer().setBackground(color);
+	}
+
+	public void setFont(Font font) {
+		getNameViewer().getTextWidget().setFont(font);
+	}
+
+	public NameViewer getNameViewer() {
+		if (nameViewer == null) {
+			throw new RuntimeException(
+					"The Name Viewer is corrupt for Name Container: " //$NON-NLS-1$
+							+ getTaxonBase().getName().getTitleCache());
+		}
+		return nameViewer;
+	}
+
+	public void createEmptyViewerPrompt(final String prompt) {
+
+		Assert.isNotNull(getNameViewer());
+
+		final StyledText textControl = getNameViewer().getTextWidget();
+		final IDocument document = getNameViewer().getDocument();
+
+		setFocusListener(new FocusListener() {
+
+			@Override
+            public void focusGained(FocusEvent e) {
+				if (document.get().equals(prompt)) {
+					textControl.setFont(getViewerFont());
+					document.set(""); //$NON-NLS-1$
+				}
+			}
+
+			@Override
+            public void focusLost(FocusEvent e) {
+				if (document.getLength() == 0) {
+					initEmptyText();
+				}
+			}
+
+		});
+		textControl.addFocusListener(getFocusListener());
+
+		if (document.getLength() == 0) {
+			textControl.setFont(AbstractUtility
+					.getFont(Resources.FONT_DEFAULT_PROMPT));
+			document.set(prompt);
+		}
+	}
+
+	abstract protected Font getViewerFont();
+
+	protected void initEmptyText() {
+		Font defaultFont = AbstractUtility.getFont(Resources.FONT_DEFAULT_PROMPT);
+		getNameViewer().getTextWidget().setFont(defaultFont);
+
+		getNameViewer().getDocument().set(getEmptyTextPrompt());
+		placeCursor();
+	}
+
+	protected void setFocusListener(FocusListener focusListener) {
+		this.focusListener = focusListener;
+	}
+
+	private FocusListener getFocusListener() {
+		return focusListener;
+	}
+
+	public void setDirty(boolean isDirty) {
+		if (isDirty) {
+			getEditor().getManagedForm().dirtyStateChanged();
+		}
+		this.isDirty = isDirty;
+	}
+
+	@Override
+    public boolean isDirty() {
+		return isDirty;
+	}
+
+	public void setMenu(Menu menu) {
+		control.setMenu(menu);
+
+		getNameViewer().setMenu(menu);
+	}
+
+	private Control[] draggableControls;
+
+	protected void setDraggableControl(Control[] controls) {
+		draggableControls = controls;
+	}
+
+	public void setIsDraggable(boolean draggable) {
+
+		if (draggable) {
+
+			if (draggableControls == null) {
+				throw new NullPointerException(
+						"Draggable controls must be set to add draggability"); //$NON-NLS-1$
+			}
+
+			Transfer[] types = new Transfer[] { CdmDataTransfer.getInstance() };
+			int operations = DND.DROP_MOVE;
+
+			for (Control draggableControl : draggableControls) {
+				DragSource dragSource = new DragSource(draggableControl,
+						operations);
+				dragSource.setTransfer(types);
+
+				//FIXME E4 migrate dnd
+//				dragSource.addDragListener(new NameEditorDragListener(this));
+//				dragSource.setDragSourceEffect(new NameEditorDragSourceEffect(
+//						control));
+			}
+		}
+	}
+
+	private String nonEditableText;
+
+	ControlListener nonEditableResizeListener = new ControlAdapter() {
+
+		int width = 0;
+
+		@Override
+		public void controlResized(ControlEvent e) {
+			if (nonEditableInfoLabel.getBounds().width == width) {
+				return;
+			}
+			width = nonEditableInfoLabel.getBounds().width;
+			if (nonEditableInfoLabel.getBounds().width > 0) {
+				nonEditableInfoLabel.setText(Dialog.shortenText(
+						nonEditableText.toUpperCase(), nonEditableInfoLabel));
+			}
+		}
+	};
+
+	private String nonEditableHoverText;
+
+	private LabelEllipsisListener nonEditableLabelEllipsisListener;
+
+	private T data;
+
+	private boolean enabled;
+
+	/**
+	 * nonEditableInfo is a label displayed underneath a GroupedComposite's
+	 * input field. For instance, NameComposites display things like name
+	 * relations, sec. references, etc. here.
+	 *
+	 * @param info
+	 *            the text to display in the label
+	 * @param append
+	 *            whether the string should be appended to text that is already
+	 *            shown in the label
+	 */
+	public void setNonEditableInfo(String info, boolean append) {
+		// TODO non editable info should only be drawn once, when everything
+		// else is drawn
+		info = info.toUpperCase();
+
+		if (append) {
+			nonEditableText += ", " + info; //$NON-NLS-1$
+			nonEditableHoverText += "\n" + info; //$NON-NLS-1$
+		} else {
+			nonEditableText = info;
+			nonEditableHoverText = info;
+		}
+
+		if (nonEditableInfoLabel == null) {
+			nonEditableInfoLabel = getEditor().getToolkit().createLabel(
+					control, ""); //$NON-NLS-1$
+			TableWrapData layoutData = new TableWrapData(
+					TableWrapData.FILL_GRAB, TableWrapData.TOP);
+			// Set indent to viewer ruler's width
+			if (getNameViewer().getRulerControl() != null) {
+				// TODO right justify
+				layoutData.indent = NameViewer.RULER_WIDTH;
+			}
+			nonEditableInfoLabel.setLayoutData(layoutData);
+
+			nonEditableLabelEllipsisListener = new LabelEllipsisListener(
+					nonEditableInfoLabel) {
+				@Override
+				public String getLabelText() {
+					return nonEditableText.toUpperCase();
+				}
+			};
+			nonEditableInfoLabel
+					.addControlListener(nonEditableLabelEllipsisListener);
+
+			nonEditableInfoHover = new DefaultToolTip(nonEditableInfoLabel);
+			nonEditableInfoHover.setRespectDisplayBounds(true);
+
+		}
+		nonEditableInfoHover.setText(nonEditableHoverText);
+		nonEditableInfoLabel.setText(nonEditableText);
+
+		calculateAnnotations();
+	}
+
+	@Override
+    public T getData() {
+		return data;
+	}
+
+	public void setData(T data) {
+		this.data = HibernateProxyHelper.deproxy(data);
+	}
+
+	/**
+	 * If the user hitting carriage return should cause something to happen -
+	 * i.e. the creation of a new composite - call this method and override the
+	 * method handleSplitText().
+	 */
+	protected void createLineBreakListener() {
+		lineBreakListener = new LineBreakListener() {
+			@Override
+			public void handleSplitText(String text) {
+				AbstractGroupedContainerE4.this.handleSplitText(text);
+			}
+
+		};
+
+		getNameViewer().getTextWidget().addVerifyListener(lineBreakListener);
+
+	}
+
+	abstract class LabelEllipsisListener extends ControlAdapter {
+
+		private final Label label;
+		int width = 0;
+
+		LabelEllipsisListener(Label label) {
+			this.label = label;
+		}
+
+		abstract public String getLabelText();
+
+		@Override
+		public void controlResized(ControlEvent e) {
+			if (label.getBounds().width == width) {
+				return;
+			}
+			width = label.getBounds().width;
+			if (label.getBounds().width > 0) {
+				label.setText(TextHelper.shortenText(getLabelText(), label));
+			}
+		}
+	}
+
+	public void storeCursor() {
+		this.cursorPosition = getNameViewer().getCursorPosition();
+	}
+
+	/**
+	 * Puts the cursor to the position it was last seen on or to the end of line
+	 * if no former position is known.
+	 */
+	public void placeCursor() {
+		if (cursorPosition == 0) {
+			getNameViewer().setCursorToEOL();
+		} else {
+			getNameViewer().setCursorPosition(cursorPosition);
+		}
+	}
+
+	public void setGroup(AbstractGroupE4 group) {
+		this.group = group;
+	}
+
+	public void restoreColor() {
+		setBackground(backgroundColor);
+	}
+
+	@Override
+	public void initialize(IManagedForm form) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void dispose() {
+		if (getControl() != null) {
+			setMenu(null);
+			getControl().dispose();
+		}
+	}
+
+	@Override
+	public void commit(boolean onSave) {
+		if (isDirty()) {
+			persistName();
+		}
+	}
+
+	@Override
+	public boolean setFormInput(Object input) {
+		return false;
+	}
+
+	@Override
+	public void setFocus() {
+		getNameViewer().getControl().setFocus();
+	}
+
+	@Override
+	public boolean isStale() {
+		return false;
+	}
+
+	public void setDisabled(boolean disabled) {
+		this.enabled = !disabled;
+		setEnabled(enabled);
+	}
+
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+		Color color = enabled ? control.getForeground() : AbstractUtility.getColor(Resources.COLOR_DISABLED_EDITOR);
+
+		getNameViewer().getTextWidget().setEditable(enabled);
+		getNameViewer().getTextWidget().setEnabled(enabled);
+		getNameViewer().getTextWidget().setForeground(color);
+	}
+
+	public boolean isEnabled(){
+		return enabled;
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractHomotypicalGroupContainerE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractHomotypicalGroupContainerE4.java
new file mode 100644
index 000000000..0febb7366
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AbstractHomotypicalGroupContainerE4.java
@@ -0,0 +1,77 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public abstract class AbstractHomotypicalGroupContainerE4 extends AbstractGroupE4 {
+
+	private HomotypicalGroup group;
+
+	public AbstractHomotypicalGroupContainerE4(TaxonNameEditorE4 editor, HomotypicalGroup group) {
+		super(editor);
+		this.group = group;
+
+		createContent();
+	}
+
+	protected abstract void createSynonymContainer();
+
+	protected List<Synonym> getSynonyms(){
+		Taxon taxon = getEditor().getTaxon();
+		return taxon.getSynonymsInGroup(getGroup());
+	}
+
+	public void setGroup(HomotypicalGroup group) {
+		this.group = group;
+	}
+
+	public void redraw(HomotypicalGroup homotypicalGroup){
+		if(redrawNeeded(homotypicalGroup)){
+			setGroup(homotypicalGroup);
+			redraw();
+		}
+	}
+
+	protected boolean redrawNeeded(HomotypicalGroup homotypicalGroup) {
+		Taxon taxon = getEditor().getTaxon();
+		homotypicalGroup = HibernateProxyHelper.deproxy(homotypicalGroup, HomotypicalGroup.class);
+		List<Synonym> synonyms = taxon.getSynonymsInGroup(homotypicalGroup);
+
+		List<Synonym> presentSynonyms = new ArrayList<Synonym>();
+
+		for(AbstractGroupedContainerE4 container : getGroupedContainers()){
+			if(container.getData() instanceof Synonym){
+				presentSynonyms.add((Synonym) container.getData());
+			}
+		}
+
+		boolean result = ! (presentSynonyms.containsAll(synonyms) && synonyms.containsAll(presentSynonyms));
+
+		return result;
+	}
+
+	public HomotypicalGroup getGroup() {
+		return group;
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AcceptedGroupE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AcceptedGroupE4.java
new file mode 100644
index 000000000..783301e53
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AcceptedGroupE4.java
@@ -0,0 +1,100 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Color;
+
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class AcceptedGroupE4 extends AbstractHomotypicalGroupContainerE4 {
+
+	private AcceptedNameContainerE4 acceptedContainer;
+
+	public AcceptedGroupE4(TaxonNameEditorE4 editor, HomotypicalGroup group) {
+		super(editor, group);
+	}
+
+	@Override
+	public void dragEntered() {
+		Color color = AbstractUtility.getColor(Resources.COLOR_DRAG_ENTER);
+		acceptedContainer.setBackground(color);
+		super.dragEntered();
+	}
+
+	@Override
+	public void dragLeft() {
+		acceptedContainer.restoreColor();
+		super.dragLeft();
+	}
+
+	@Override
+	public List<AbstractGroupedContainerE4> getGroupedContainers() {
+		List<AbstractGroupedContainerE4> containers = new ArrayList<>();
+		containers.add(getAcceptedNameContainer());
+		containers.addAll(super.getGroupedContainers());
+		return containers;
+	}
+
+	@Override
+    protected void createContainers() {
+		this.acceptedContainer = new AcceptedNameContainerE4(getEditor().getTaxon());
+		acceptedContainer.setGroup(this);
+
+		acceptedContainer.createContent();
+
+		createSynonymContainer();
+	}
+
+	@Override
+    protected void createSynonymContainer(){
+		for(Synonym synonym : getSynonyms()){
+		    SynonymContainerE4 container = new SynonymContainerE4(this, synonym);
+			this.add(container);
+			container.createContent();
+		}
+	}
+
+	public void setAcceptedNameContainer(AcceptedNameContainerE4 acceptedNameContainer) {
+		this.acceptedContainer = acceptedNameContainer;
+		acceptedContainer.setGroup(this);
+	}
+
+	public AcceptedNameContainerE4 getAcceptedNameContainer(){
+		return acceptedContainer;
+	}
+
+	@Override
+	protected void emptyGroup() {
+		acceptedContainer.dispose();
+		acceptedContainer = null;
+		super.emptyGroup();
+	}
+
+	@Override
+	protected boolean redrawNeeded(HomotypicalGroup homotypicalGroup) {
+		if(! acceptedContainer.getData().equals(getEditor().getTaxon())){
+			return true;
+		}
+		return super.redrawNeeded(homotypicalGroup);
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AcceptedNameContainerE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AcceptedNameContainerE4.java
new file mode 100644
index 000000000..e4e1d6e16
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/AcceptedNameContainerE4.java
@@ -0,0 +1,64 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import org.eclipse.swt.graphics.Font;
+
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+public class AcceptedNameContainerE4 extends AbstractGroupedContainerE4<Taxon> {
+
+	private AcceptedGroupE4 acceptedGroup;
+
+	public AcceptedNameContainerE4(Taxon taxon) {
+		super(taxon);
+	}
+
+	@Override
+    public void initializeComposite(){
+		setFont(getViewerFont());
+
+		initTextViewer();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected Font getViewerFont() {
+		return AbstractUtility.getFont(Resources.ACCEPTED_TAXON_FONT);
+	}
+
+	public void setGroup(AcceptedGroupE4 group) {
+		this.acceptedGroup = group;
+	}
+
+	@Override
+	public AbstractGroupE4 getGroup() {
+		return acceptedGroup;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected void updateNonEditableInfo() {
+		// not needed
+	}
+
+
+	@Override
+	protected void updateIcon() {
+		setIcon(ACCEPTED_ICON);
+	}
+
+	@Override
+	protected void updateIndent() {
+		setIndent(ACCEPTED_INDENT);
+	}
+
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/ContainerFactoryE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/ContainerFactoryE4.java
new file mode 100644
index 000000000..0e261332c
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/ContainerFactoryE4.java
@@ -0,0 +1,94 @@
+/**
+ *
+ */
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class ContainerFactoryE4 {
+
+	public static void createOrUpdateAcceptedTaxonsHomotypicGroup(
+	        TaxonNameEditorE4 taxonNameEditor) {
+
+		if(taxonNameEditor.getAcceptedGroup() == null){
+			taxonNameEditor.setAcceptedGroup(new AcceptedGroupE4(taxonNameEditor, taxonNameEditor.getTaxon().getHomotypicGroup()));
+		}
+		else{
+			taxonNameEditor.getAcceptedGroup().redraw(taxonNameEditor.getTaxon().getHomotypicGroup());
+		}
+
+	}
+
+	public static void createOrUpdateHeterotypicSynonymyGroups(
+			TaxonNameEditorE4 taxonNameEditor) {
+		List<HomotypicalSynonymGroupE4> retainedGroups = new ArrayList<>();
+
+		List<HomotypicalSynonymGroupE4> heterotypicSynonymGroups = taxonNameEditor.getHeterotypicSynonymGroups();
+
+		if (heterotypicSynonymGroups != null) {
+
+			for(HomotypicalSynonymGroupE4 group : heterotypicSynonymGroups){
+				retainedGroups.add(group);
+			}
+		}
+
+		for(HomotypicalGroup homotypicalGroup : taxonNameEditor.getTaxon().getHeterotypicSynonymyGroups()){
+		    HomotypicalSynonymGroupE4 group = createOrUpdateHeterotypicSynonymyGroup(taxonNameEditor, homotypicalGroup);
+
+			retainedGroups.remove(group);
+		}
+
+		for(HomotypicalSynonymGroupE4 retainedGroup : retainedGroups){
+			taxonNameEditor.removeGroup(retainedGroup);
+		}
+	}
+
+
+	public static HomotypicalSynonymGroupE4 createOrUpdateHeterotypicSynonymyGroup(
+	        TaxonNameEditorE4 taxonNameEditor, HomotypicalGroup homotypicalGroup){
+	    HomotypicalSynonymGroupE4 group = null;
+		if(taxonNameEditor.getHomotypicalGroupContainer(homotypicalGroup) == null){
+			group = new HomotypicalSynonymGroupE4(taxonNameEditor, homotypicalGroup);
+			taxonNameEditor.addHeterotypicSynonymGroup(group);
+			if(taxonNameEditor.getMisappliedGroup() != null){
+				group.getControl().moveAbove(taxonNameEditor.getMisappliedGroup().getControl());
+			}
+		}
+		else{
+			group = taxonNameEditor.getHomotypicalGroupContainer(homotypicalGroup);
+			group.redraw(homotypicalGroup);
+		}
+
+		return group;
+	}
+
+	public static void createOrUpdateMisapplicationsGroup(
+	        TaxonNameEditorE4 taxonNameEditor) {
+		MisappliedGroupE4 group = taxonNameEditor.getMisappliedGroup();
+		Taxon taxon = HibernateProxyHelper.deproxy(taxonNameEditor.getTaxon(), Taxon.class);
+		if(taxon.getMisappliedNames().isEmpty()){
+			taxonNameEditor.removeGroup(group);
+			taxonNameEditor.setMisapplicationsGroup(null);
+		}else{
+			if(group == null){
+				taxonNameEditor.setMisapplicationsGroup(new MisappliedGroupE4(taxonNameEditor));
+			}else{
+				group.redraw();
+			}
+		}
+
+	}
+
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/HomotypicalSynonymGroupE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/HomotypicalSynonymGroupE4.java
new file mode 100644
index 000000000..7e45e790c
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/HomotypicalSynonymGroupE4.java
@@ -0,0 +1,57 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import org.eclipse.swt.graphics.Image;
+
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.taxeditor.editor.name.container.IContainerConstants;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class HomotypicalSynonymGroupE4 extends AbstractHomotypicalGroupContainerE4 {
+
+	public HomotypicalSynonymGroupE4(TaxonNameEditorE4 editor, HomotypicalGroup group) {
+		super(editor, group);
+	}
+
+	@Override
+	protected void createContainers() {
+		createSynonymContainer();
+	}
+
+	@Override
+    protected void createSynonymContainer(){
+		int i = 0;
+		int indent = IContainerConstants.SYNONYM_INDENT;
+		Image icon = IContainerConstants.HETEROTYPIC_SYNONYM_ICON;
+		for(Synonym synonym : getSynonyms()){
+			if(i > 0){
+				indent = IContainerConstants.HOMOTYPIC_SYNONYM_IN_HETEROTYPIC_GROUP_INDENT;
+				icon = IContainerConstants.HOMOTYPIC_SYNONYM_IN_HETEROTYPIC_GROUP_ICON;
+			}
+			SynonymContainerE4 container = new SynonymContainerE4(this, synonym, indent, icon);
+			this.add(container);
+			container.createContent();
+			i++;
+		}
+	}
+
+	@Override
+	protected boolean redrawNeeded(HomotypicalGroup homotypicalGroup) {
+		return super.redrawNeeded(homotypicalGroup);
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/MisapplicationContainerE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/MisapplicationContainerE4.java
new file mode 100644
index 000000000..1963beda2
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/MisapplicationContainerE4.java
@@ -0,0 +1,173 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.swt.graphics.Font;
+
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.editor.name.container.EditorAnnotation;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.model.NameHelper;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class MisapplicationContainerE4 extends AbstractGroupedContainerE4<Taxon> {
+	TaxonRelationship misapplication;
+
+	public MisapplicationContainerE4(AbstractGroupE4 group, Taxon misappliedName) {
+		super(misappliedName);
+
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected void initializeComposite() {
+		setIsDraggable(true);
+		setFont(getViewerFont());
+		TaxonNameEditorE4 editor = getEditor();
+		Taxon taxon = editor.getTaxon();
+		for (TaxonRelationship rel: taxon.getTaxonRelations(getMisappliedName())){
+			if (rel.getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
+				misapplication = rel;
+				break;
+			}
+		}
+		showSec();
+
+		initTextViewer();
+	}
+
+	@Override
+	protected void updateIcon() {
+		setIcon(MISAPPLIEDNAME_ICON);
+	}
+
+	private void showSec() {
+		if (getMisappliedName() == null) {
+			return;
+		}
+		String title = "";
+		String author = "";
+		TaxonName misappliedNameName = HibernateProxyHelper.deproxy(getMisappliedName().getName());
+		if (StringUtils.isNotBlank(misappliedNameName.getAuthorshipCache())){
+			author = ", non " + misappliedNameName.getAuthorshipCache();
+		}
+		if (getMisappliedName().getSec() == null) {
+		    if (getMisappliedName().getAppendedPhrase() != null ){
+		        title = getMisappliedName().getAppendedPhrase();
+		    }else{
+		        title = "auct.";
+
+		    }
+
+		} else {
+			String sec = " sensu ";
+			if (getMisappliedName().getAppendedPhrase() != null ){
+			    sec = getMisappliedName().getAppendedPhrase() + " " + sec;
+			}
+			title += sec + getMisappliedName().getSec().getTitleCache();
+		}
+		title += author;
+		title = title.replace("&", "&&");
+		setNonEditableInfo(title, false);
+	}
+
+	public Taxon getMisappliedName() {
+		return getTaxonBase();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected Font getViewerFont() {
+		return AbstractUtility.getFont(Resources.MISAPPLIEDNAME_FONT);
+	}
+
+	@Override
+	public void showAnnotations() {
+		if(getData().getSec() == null){
+			getNameViewer().addAnnotation(
+					new EditorAnnotation(0, Messages.MisapplicationContainer_SEC_REF_REQUIRED));
+		}
+		super.showAnnotations();
+	}
+
+
+	/** {@inheritDoc} */
+	@Override
+	protected void updateNonEditableInfo() {
+		showSec();
+	}
+
+	@Override
+	protected void updateIndent() {
+		setIndent(MISAPPLIEDNAME_INDENT);
+	}
+
+	@Override
+	protected void initTextViewer() {
+
+		// showNameRelations();
+
+		updateIndent();
+
+		updateIcon();
+
+		String text = NameHelper.getDisplayNameCache(getData());
+
+		if (text.length() == 0) {
+			initEmptyText();
+		} else {
+			getNameViewer().setText(text);
+			placeCursor();
+		}
+		calculateAnnotations();
+	}
+
+	@Override
+    public void refresh() {
+		// showNameRelations();
+
+		String text = NameHelper.getDisplayNameCache(getData());
+
+		if (getNameViewer().getTextWidget() == null) {
+			// we might get here via dnd. Look slike it can be ignored
+			return;
+		}
+
+		if (text.length() == 0) {
+			initEmptyText();
+		} else if (!getNameViewer().getTextWidget().getText().equals(text)) {
+			removeListener();
+			getNameViewer().getTextWidget().setText(text);
+			addListener();
+		}
+
+		updateNonEditableInfo();
+
+		updateIcon();
+		// placeCursor();
+		updateIndent();
+
+		enableFreeText();
+	}
+
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/MisappliedGroupE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/MisappliedGroupE4.java
new file mode 100644
index 000000000..fe9d8c6ab
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/MisappliedGroupE4.java
@@ -0,0 +1,58 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class MisappliedGroupE4 extends AbstractGroupE4{
+
+	public MisappliedGroupE4(TaxonNameEditorE4 editor) {
+		super(editor);
+
+		createContent();
+	}
+
+	@Override
+	protected void createContainers() {
+		for(Taxon misapplication : getEditor().getTaxon().getMisappliedNames()){
+		    MisapplicationContainerE4 container = new MisapplicationContainerE4(this, misapplication);
+			this.add(container);
+			container.createContent();
+		}
+	}
+
+	@Override
+	public void redraw() {
+		if(redrawNeeded()){
+			super.redraw();
+		}
+	}
+
+	private boolean redrawNeeded() {
+		Set<Taxon> misapplications = getEditor().getTaxon().getMisappliedNames();
+
+		Set<Taxon> presentMisapplication = new HashSet<Taxon>();
+
+		for (AbstractGroupedContainerE4<Taxon> container  : getGroupedContainers()){
+			presentMisapplication.add(container.getData());
+		}
+		return ! (presentMisapplication.containsAll(misapplications) && misapplications.containsAll(presentMisapplication));
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/SynonymContainerE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/SynonymContainerE4.java
new file mode 100644
index 000000000..bb4ebf08a
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/container/SynonymContainerE4.java
@@ -0,0 +1,142 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.editor.name.e4.container;
+
+import java.util.Set;
+
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.taxeditor.editor.EditorUtil;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+/**
+ * <p>SynonymContainer class.</p>
+ *
+ * @author p.ciardelli
+ * @created 13.01.2009
+ * @version 1.0
+ */
+public class SynonymContainerE4 extends AbstractGroupedContainerE4<Synonym> {
+
+	private int indent = SYNONYM_INDENT;
+	private Image icon = HETEROTYPIC_SYNONYM_ICON;
+
+	/**
+	 * <p>Constructor for SynonymContainer.</p>
+	 *
+	 * @param editor a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor} object.
+	 * @param group a {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup} object.
+	 * @param synonym a {@link eu.etaxonomy.cdm.model.taxon.Synonym} object.
+	 */
+	public SynonymContainerE4(AbstractHomotypicalGroupContainerE4 group, Synonym synonym) {
+		super(synonym);
+	}
+
+	public SynonymContainerE4(AbstractHomotypicalGroupContainerE4 group, Synonym synonym, int indent, Image icon){
+		super(synonym);
+		this.indent = indent;
+		this.icon = icon;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected void initializeComposite() {
+		setIsDraggable(true);
+		setFont(getViewerFont());
+
+		if(getName() == null){
+			MessagingUtils.warn(getClass(), Messages.SynonymContainer_SYNONYM_NULL_NAME);
+		}
+
+		initTextViewer();
+	}
+
+	@Override
+    protected void updateIcon(){
+		TaxonName name = getName();
+
+
+		if(! name.getStatus().isEmpty()){
+
+			Set<NomenclaturalStatus> allStatus = name.getStatus();
+
+			for (NomenclaturalStatus status : allStatus){
+				if(status.getType() != null && (status.getType().isInvalidType())){
+					setIcon(INVALID_OR_NUDUM_NAME_ICON);
+					return;
+				}
+			}
+		}
+
+		if (isHomotypic()) {
+			if(name.isGroupsBasionym()){
+				setIcon(HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON);
+			}else{
+				setIcon(HOMOTYPIC_SYNONYM_ICON);
+			}
+
+			return;
+		} else{
+			if(name.isGroupsBasionym()){
+				setIcon(HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON);
+				return;
+			}
+		}
+
+		setIcon(icon);
+
+	}
+
+	private boolean isHomotypic() {
+		HomotypicalGroup group = getSynonym().getHomotypicGroup();
+		return group.equals(getEditor().getTaxon().getHomotypicGroup());
+	}
+
+	/**
+	 * <p>getSynonym</p>
+	 *
+	 * @return a {@link eu.etaxonomy.cdm.model.taxon.Synonym} object.
+	 */
+	public Synonym getSynonym() {
+		return getTaxonBase();
+	}
+
+
+	/**
+	 * <p>getViewerFont</p>
+	 *
+	 * @return a {@link org.eclipse.swt.graphics.Font} object.
+	 */
+	@Override
+    protected Font getViewerFont() {
+		return EditorUtil.getFont(Resources.SYNONYM_FONT);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected void updateNonEditableInfo() {
+		// not needed
+	}
+
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.taxeditor.editor.name.AbstractGroupedContainer#updateIndent()
+	 */
+	@Override
+	protected void updateIndent() {
+		setIndent(this.indent );
+	}
+}
diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/dnd/NameEditorDropTargetListenerE4.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/dnd/NameEditorDropTargetListenerE4.java
new file mode 100644
index 000000000..dd072747f
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/name/e4/dnd/NameEditorDropTargetListenerE4.java
@@ -0,0 +1,162 @@
+/**
+ *
+ */
+package eu.etaxonomy.taxeditor.editor.name.e4.dnd;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetAdapter;
+import org.eclipse.swt.dnd.DropTargetEvent;
+
+import eu.etaxonomy.cdm.model.common.ICdmBase;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.taxeditor.editor.EditorUtil;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
+import eu.etaxonomy.taxeditor.editor.name.container.AbstractHomotypicalGroupContainer;
+import eu.etaxonomy.taxeditor.editor.name.e4.IDropTargetableE4;
+import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
+
+/**
+ *
+ * @author pplitzner
+ * @date Aug 24, 2017
+ *
+ */
+public class NameEditorDropTargetListenerE4 extends DropTargetAdapter {
+
+	private IDropTargetableE4 target;
+
+	public NameEditorDropTargetListenerE4(IDropTargetableE4 target){
+		this.target = target;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void dragEnter(DropTargetEvent dropTargetEvent) {
+		target.dragEntered();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void dragLeave(DropTargetEvent dropTargetEvent) {
+		target.dragLeft();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+    public void drop(DropTargetEvent dropTargetEvent) {
+
+		TaxonBase taxonBase = getDroppedTaxonBase(dropTargetEvent);
+
+		Assert.isNotNull(taxonBase);
+
+		if(taxonBase.getHomotypicGroup().equals(getHomotypicalGroup())){
+			// do nothing when dragged to the same group
+			dropTargetEvent.detail = DND.DROP_NONE;
+			return;
+		}
+
+		// Execute operations at end of drag event
+		AbstractPostOperation operation = createOperation(taxonBase);
+
+		// Execute operation if it has been initiated
+		if (operation == null) {
+			MessagingUtils.warn(getClass(), String.format(Messages.NameEditorDropTargetListener_UNSUCCESSFULL_DROP, taxonBase.getClass(), target));
+			dropTargetEvent.detail = DND.DROP_NONE;
+		} else {
+			AbstractUtility.executeOperation(operation);
+		}
+		target.getEditor().getConversationHolder().commit();
+		if (!target.equals(EditorUtil.getActiveMultiPageTaxonEditor().getActiveEditor())){
+			((TaxonNameEditor)EditorUtil.getActiveMultiPageTaxonEditor().getActiveEditor()).redraw();
+			((TaxonNameEditor)EditorUtil.getActiveMultiPageTaxonEditor().getActiveEditor()).getConversationHolder().commit();
+
+		}
+		target.getEditor().redraw();
+
+	}
+
+	private AbstractPostOperation createOperation(TaxonBase taxonBase) {
+
+	    //FIXME E4 migrate dnd
+
+//		if(taxonBase instanceof Synonym){
+//			Synonym synonym = (Synonym) taxonBase;
+//
+//			if(target instanceof AbstractHomotypicalGroupContainer){
+//				HomotypicalGroup homotypicalGroup = ((AbstractHomotypicalGroupContainer) target).getGroup();
+//
+//				return new ChangeHomotypicGroupOperation(Messages.NameEditorDropTargetListener_CHANGE_HOMOTYPICAL_GROUP, getEditor().getUndoContext(),
+//						getEditor().getTaxon(), synonym, homotypicalGroup, target);
+//			}
+//			else if(target instanceof MisappliedGroup){
+//				return new ChangeSynonymToMisapplicationOperation(Messages.NameEditorDropTargetListener_CHANGE_SYNONYM_TO_MISAPP, getEditor().getUndoContext(),
+//						getEditor().getTaxon(), synonym, target);
+//			}
+//			else if(target instanceof TaxonNameEditor){
+//				if (target.equals(getEditor())){
+//					return new ChangeHomotypicGroupOperation(Messages.NameEditorDropTargetListener_CHANGE_HOMOTYPICAL_GROUP, getEditor().getUndoContext(),
+//						getEditor().getTaxon(), synonym, null, target);
+//				} else{
+//					getEditor().getConversationHolder().commit();
+//					((TaxonNameEditor) target).getConversationHolder().commit();
+//
+//					return new MoveSynonymToAnotherAcceptedTaxonOperation(Messages.NameEditorDropTargetListener_CHANGE_ACC_TAXON, getEditor().getUndoContext(), getEditor().getTaxon().getUuid(), synonym.getUuid(), ((TaxonNameEditor) target).getTaxon(), null );
+//
+//				}
+//			}
+//
+//		}else if(taxonBase instanceof Taxon){
+//			Taxon concept = (Taxon) taxonBase;
+//
+//			if(target instanceof AbstractHomotypicalGroupContainer){
+//				HomotypicalGroup homotypicalGroup = ((AbstractHomotypicalGroupContainer) target).getGroup();
+//
+//				return new ChangeConceptToSynonymOperation(Messages.NameEditorDropTargetListener_CHANGE_SYNONYM, getEditor().getUndoContext(),
+//						getEditor().getTaxon(), concept, homotypicalGroup, target);
+//			}
+//			else if(target instanceof MisappliedGroup ){
+//				return new ChangeConceptRelationshipTypeOperation(Messages.NameEditorDropTargetListener_CHANGE, getEditor().getUndoContext(),
+//						getEditor().getTaxon(), concept, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), target);
+//			}
+//		}
+
+
+		return null;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void dropAccept(DropTargetEvent event) {
+		// pass
+	}
+
+
+	private HomotypicalGroup getHomotypicalGroup() {
+		if(target instanceof AbstractHomotypicalGroupContainer){
+			return ((AbstractHomotypicalGroupContainer) target).getGroup();
+		}
+		return null;
+	}
+
+	private TaxonBase getDroppedTaxonBase(DropTargetEvent dropTargetEvent){
+		if(dropTargetEvent.data instanceof ICdmBase[]){
+
+			ICdmBase[] cdmBaseObjects = (ICdmBase[]) dropTargetEvent.data;
+
+			if(cdmBaseObjects[0] instanceof TaxonBase){
+				return (TaxonBase) cdmBaseObjects[0];
+			}
+		}
+		return null;
+	}
+
+	private TaxonNameEditorE4 getEditor() {
+		return (TaxonNameEditorE4) EditorUtil.getActiveMultiPageTaxonEditor().getActiveEditor();
+	}
+}
