You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2011/01/04 21:12:22 UTC

svn commit: r1055170 - /incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/

Author: marrs
Date: Tue Jan  4 20:12:22 2011
New Revision: 1055170

URL: http://svn.apache.org/viewvc?rev=1055170&view=rev
Log:
Started refactoring the huge UI class into smaller, more manageable ones.

Added:
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AbstractAddWindow.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/Associations.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedArtifactObject.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedDistributionObject.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedFeatureObject.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedObject.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedTargetObject.java
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/OBREntry.java
Modified:
    incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AbstractAddWindow.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AbstractAddWindow.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AbstractAddWindow.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/AbstractAddWindow.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,63 @@
+package org.apache.ace.webui.vaadin;
+
+import com.vaadin.ui.Button;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+import com.vaadin.ui.Button.ClickEvent;
+
+public abstract class AbstractAddWindow extends Window {
+    private final Window m_main;
+    private final TextField m_name;
+
+    public AbstractAddWindow(final Window main, String caption) {
+        m_main = main;
+        setModal(true);
+        setWidth("15em");
+        setCaption(caption);
+
+        // Configure the windws layout; by default a VerticalLayout
+        VerticalLayout layout = (VerticalLayout) getContent();
+        layout.setMargin(true);
+        layout.setSpacing(true);
+
+        m_name = new TextField("name");
+        final TextField description = new TextField("description");
+
+        layout.addComponent(m_name);
+        layout.addComponent(description);
+
+        Button close = new Button("Ok", new Button.ClickListener() {
+            // inline click-listener
+            public void buttonClick(ClickEvent event) {
+                // close the window by removing it from the parent window
+                (getParent()).removeWindow(AbstractAddWindow.this);
+                // create the feature
+                create((String) m_name.getValue(), (String) description.getValue());
+            }
+        });
+        // The components added to the window are actually added to the window's
+        // layout; you can use either. Alignments are set using the layout
+        layout.addComponent(close);
+        layout.setComponentAlignment(close, "right");
+    }
+
+    public void show() {
+        if (getParent() != null) {
+            // window is already showing
+            m_main.getWindow().showNotification(
+                    "Window is already open");
+        } else {
+            // Open the subwindow by adding it to the parent
+            // window
+            m_main.getWindow().addWindow(this);
+        }
+        setRelevantFocus();
+    }
+
+    private void setRelevantFocus() {
+        m_name.focus();
+    }
+
+    protected abstract void create(String name, String description);
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/ArtifactTable.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,16 @@
+package org.apache.ace.webui.vaadin;
+
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Window;
+
+public class ArtifactTable extends Table {
+    public ArtifactTable(final Window main) {
+        super("Artifacts");
+        addContainerProperty("symbolic name", String.class, null);
+        addContainerProperty("version", String.class, null);
+        setSizeFull();
+        setSelectable(true);
+        setMultiSelect(true);
+        setImmediate(true);
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/Associations.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/Associations.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/Associations.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/Associations.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,274 @@
+package org.apache.ace.webui.vaadin;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ace.client.repository.ObjectRepository;
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.object.GatewayObject;
+import org.apache.ace.client.repository.object.GroupObject;
+import org.apache.ace.client.repository.object.LicenseObject;
+import org.apache.ace.client.repository.stateful.StatefulGatewayObject;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.CellStyleGenerator;
+
+public class Associations {
+    private List<RepositoryObject> m_associatedItems = new ArrayList<RepositoryObject>();
+    private List<RepositoryObject> m_relatedItems = new ArrayList<RepositoryObject>();
+    private Table m_activeTable;
+    private Set<?> m_activeSelection;
+    private SelectionListener m_activeSelectionListener;
+	
+    public void removeAssociatedItem(RepositoryObject item) {
+    	m_associatedItems.remove(item);
+    }
+    
+    public void clear() {
+    	m_associatedItems.clear();
+    	m_relatedItems.clear();
+    }
+    
+    public boolean isActiveTable(Table table) {
+    	return m_activeTable.equals(table);
+    }
+    
+    public Set<?> getActiveSelection() {
+    	return m_activeSelection;
+    }
+    
+    public RepositoryObject lookupInActiveSelection(Object item) {
+    	return m_activeSelectionListener.lookup(item);
+    }
+    
+    public void addAssociatedItems(List items) {
+    	m_associatedItems.addAll(items);
+    }
+    
+    public void addRelatedItems(List items) {
+    	m_relatedItems.addAll(items);
+    }
+    
+    public CellStyleGenerator createCellStyleGenerator() {
+    	return new CellStyleGenerator() {
+            public String getStyle(Object itemId, Object propertyId) {
+                if (propertyId == null) {
+                    // no propertyId, styling row
+                    for (RepositoryObject o : m_associatedItems) {
+                        System.out.println("cellrenderer probing: " + o);
+                        if (equals(itemId, o)) {
+                            System.out.println(" -> associated");
+                            return "associated";
+                        }
+                    }
+                    for (RepositoryObject o : m_relatedItems) {
+                        if (equals(itemId, o)) {
+                            System.out.println(" -> related");
+                            return "related";
+                        }
+                    }
+                    System.out.println("cellrenderer: unrelated");
+                }
+                return null;
+            }
+            public boolean equals(Object itemId, RepositoryObject object) {
+                return (getNamedObject(object).getName().equals(itemId));
+            }
+    	};
+    }
+    
+    public NamedObject getNamedObject(RepositoryObject object) {
+    	if (object instanceof ArtifactObject) {
+    		return new NamedArtifactObject((ArtifactObject) object);
+    	}
+    	else if (object instanceof GroupObject) {
+    		return new NamedFeatureObject((GroupObject) object);
+    	}
+    	else if (object instanceof LicenseObject) {
+    		return new NamedDistributionObject((LicenseObject) object);
+    	}
+    	else if (object instanceof GatewayObject) {
+    		return new NamedTargetObject((GatewayObject) object);
+    	}
+    	return null;
+    }
+    
+    /**
+     * Helper method to find all related {@link RepositoryObject}s in a given 'direction'
+     */
+    private <FROM extends RepositoryObject, TO extends RepositoryObject> List<TO> getRelated(FROM from, Class<TO> toClass) {
+        // if the SGO is not backed by a GO yet, this will cause an exception
+        return from.getAssociations(toClass);
+    }
+    
+    /**
+     * Helper method to find all related {@link RepositoryObject}s in a given 'direction', starting with a list of objects
+     */
+    private <FROM extends RepositoryObject, TO extends RepositoryObject> List<TO> getRelated(List<FROM> from, Class<TO> toClass) {
+        List<TO> result = new ArrayList<TO>();
+        for (RepositoryObject o : from) {
+            result.addAll(getRelated(o, toClass));
+        }
+        return result;
+    }
+
+    
+    public class SelectionListener implements Table.ValueChangeListener {
+        private final Table m_table;
+        private final Table[] m_tablesToRefresh;
+        private final ObjectRepository<? extends RepositoryObject> m_repository;
+        private final Class[] m_left;
+        private final Class[] m_right;
+                    
+        public SelectionListener(final Table table, final ObjectRepository<? extends RepositoryObject> repository, final Class[] left, final Class[] right, final Table[] tablesToRefresh) {
+        	m_table = table;
+        	m_repository = repository;
+        	m_left = left;
+        	m_right = right;
+        	m_tablesToRefresh = tablesToRefresh;
+        }
+        
+        public void valueChange(ValueChangeEvent event) {
+            
+            if (m_activeSelection != null && m_activeTable != null) {
+                if (m_activeTable.equals(m_table)) {
+                    System.out.println("SAME TABLE!");
+                }
+                else {
+                    for (Object val : m_activeSelection) {
+                        m_activeTable.unselect(val);
+                    }
+                    m_table.requestRepaint();
+                }
+            }
+            
+            m_activeSelectionListener = SelectionListener.this;
+            
+            // set the active table
+            m_activeTable = m_table;
+            
+            // in multiselect mode, a Set of itemIds is returned,
+            // in singleselect mode the itemId is returned directly
+            Set<?> value = (Set<?>) event.getProperty().getValue();
+            if (null == value || value.size() == 0) {
+//                    selected.setValue("No selection");
+            } else {
+//                    selected.setValue("Selected: " + table.getValue());
+            }
+
+            // remember the active selection too
+            m_activeSelection = value;
+
+            if (value == null) {
+                System.out.println("no selection");
+            }
+            else {
+                System.out.println("selection:");
+
+                clear();
+
+                for (Object val : value) {
+                    System.out.println(" - " + m_table.getItem(val).getItemProperty(VaadinClient.OBJECT_NAME) + " " + val);
+                    RepositoryObject lo = lookup(val);
+                    System.out.println("lookup(" + val + ") returned " + lo);
+                    if (lo != null) {
+                        List related = null;
+                        for (int i = 0; i < m_left.length; i++) {
+                            if (i == 0) {
+                                related = getRelated(lo, m_left[i]);
+                                System.out.println("left associated:");
+                                for (Object o : related) {
+                                    System.out.println(" -> " + o);
+                                }
+                                m_associatedItems.addAll(related);
+                            }
+                            else {
+                                related = getRelated(related, m_left[i]);
+                                System.out.println("left related:");
+                                for (Object o : related) {
+                                    System.out.println(" -> " + o);
+                                }
+                                m_relatedItems.addAll(related);
+                            }
+                        }
+                        for (int i = 0; i < m_right.length; i++) {
+                            if (i == 0) {
+                                related = getRelated(lo, m_right[i]);
+                                System.out.println("right associated:");
+                                for (Object o : related) {
+                                    System.out.println(" -> " + o);
+                                }
+                                m_associatedItems.addAll(related);
+                            }
+                            else {
+                                related = getRelated(related, m_right[i]);
+                                System.out.println("right related:");
+                                for (Object o : related) {
+                                    System.out.println(" -> " + o);
+                                }
+                                m_relatedItems.addAll(related);
+                            }
+                        }
+                    }
+                    System.out.println("summarizing associated:");
+                    for (RepositoryObject ro : m_associatedItems) {
+                        System.out.println("** " + ro);
+                    }
+                    System.out.println("summarizing related:");
+                    for (RepositoryObject ro : m_relatedItems) {
+                        System.out.println("** " + ro);
+                    }
+                    
+                    for (Table t : m_tablesToRefresh) {
+                        System.out.println("refreshing " + t);
+                        t.requestRepaint();
+                    }
+                    
+                    System.out.println("summarizing associated:");
+                    for (RepositoryObject ro : m_associatedItems) {
+                        System.out.println("** " + ro);
+                    }
+                    System.out.println("summarizing related:");
+                    for (RepositoryObject ro : m_relatedItems) {
+                        System.out.println("** " + ro);
+                    }
+                }
+            }
+        }
+
+        public RepositoryObject lookup(Object value) {
+            for (RepositoryObject object : m_repository.get()) {
+                System.out.println("..." + object);
+                if (object instanceof StatefulGatewayObject) {
+                    StatefulGatewayObject sgo = (StatefulGatewayObject) object;
+                    if (sgo.isRegistered()) {
+                        object = sgo.getGatewayObject();
+                    }
+                    else {
+                        object = null;
+                    }
+                }
+                if (object != null) {
+                    NamedObject namedObject = getNamedObject(object);
+                    System.out.println("..." + namedObject);
+                    if (namedObject != null) {
+                        if (namedObject.getName().equals(value)) {
+                            System.out.println("Found: " + namedObject.getName());
+                            return object;
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+		
+    	
+    }
+    
+    public SelectionListener createSelectionListener(final Table table, final ObjectRepository<? extends RepositoryObject> repository, final Class[] left, final Class[] right, final Table[] tablesToRefresh) {
+    	return new SelectionListener(table, repository, left, right, tablesToRefresh);
+    }
+}

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedArtifactObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedArtifactObject.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedArtifactObject.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedArtifactObject.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,23 @@
+package org.apache.ace.webui.vaadin;
+
+import org.apache.ace.client.repository.object.ArtifactObject;
+
+public class NamedArtifactObject implements NamedObject {
+    private final ArtifactObject m_target;
+
+    public NamedArtifactObject(ArtifactObject target) {
+        m_target = target;
+    }
+
+    public String getName() {
+        return m_target.getName();
+    }
+
+    public String getDescription() {
+        return m_target.getDescription();
+    }
+
+    public void setDescription(String description) {
+        m_target.setDescription(description);
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedDistributionObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedDistributionObject.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedDistributionObject.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedDistributionObject.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,23 @@
+package org.apache.ace.webui.vaadin;
+
+import org.apache.ace.client.repository.object.LicenseObject;
+
+public class NamedDistributionObject implements NamedObject {
+    private final LicenseObject m_target;
+
+    public NamedDistributionObject(LicenseObject target) {
+        m_target = target;
+    }
+
+    public String getName() {
+        return m_target.getName();
+    }
+
+    public String getDescription() {
+        return m_target.getDescription();
+    }
+
+    public void setDescription(String description) {
+        m_target.setDescription(description);
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedFeatureObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedFeatureObject.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedFeatureObject.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedFeatureObject.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,23 @@
+package org.apache.ace.webui.vaadin;
+
+import org.apache.ace.client.repository.object.GroupObject;
+
+public class NamedFeatureObject implements NamedObject {
+    private final GroupObject m_target;
+
+    public NamedFeatureObject(GroupObject target) {
+        m_target = target;
+    }
+
+    public String getName() {
+        return m_target.getName();
+    }
+
+    public String getDescription() {
+        return m_target.getDescription();
+    }
+
+    public void setDescription(String description) {
+        m_target.setDescription(description);
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedObject.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedObject.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedObject.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,7 @@
+package org.apache.ace.webui.vaadin;
+
+public interface NamedObject {
+    String getName();
+    String getDescription();
+    void setDescription(String description);
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedTargetObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedTargetObject.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedTargetObject.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/NamedTargetObject.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,23 @@
+package org.apache.ace.webui.vaadin;
+
+import org.apache.ace.client.repository.object.GatewayObject;
+
+class NamedTargetObject implements NamedObject {
+    private final GatewayObject m_target;
+
+    public NamedTargetObject(GatewayObject target) {
+        m_target = target;
+    }
+
+    public String getName() {
+        return m_target.getID();
+    }
+
+    public String getDescription() {
+        return "";
+    }
+
+    public void setDescription(String description) {
+        throw new IllegalArgumentException();
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/OBREntry.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/OBREntry.java?rev=1055170&view=auto
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/OBREntry.java (added)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/OBREntry.java Tue Jan  4 20:12:22 2011
@@ -0,0 +1,35 @@
+package org.apache.ace.webui.vaadin;
+
+public class OBREntry {
+    private final String m_symbolicName;
+    private final String m_version;
+    private final String m_uri;
+    
+    public OBREntry(String symbolicName, String version, String uri) {
+        m_symbolicName = symbolicName;
+        m_version = version;
+        m_uri = uri;
+    }
+    
+    public String getVersion() {
+        return m_version;
+    }
+    
+    public String getSymbolicName() {
+        return m_symbolicName;
+    }
+    
+    public String getUri() {
+        return m_uri;
+    }
+
+    @Override
+    public int hashCode() {
+        return m_uri.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return m_uri.equals(((OBREntry) obj).m_uri);
+    }
+}
\ No newline at end of file

Modified: incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java?rev=1055170&r1=1055169&r2=1055170&view=diff
==============================================================================
--- incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java (original)
+++ incubator/ace/trunk/ace-webui-vaadin/src/main/java/org/apache/ace/webui/vaadin/VaadinClient.java Tue Jan  4 20:12:22 2011
@@ -118,9 +118,10 @@ TODO:
  - Add buttons to create new items in all of the tables (done for those that make sense)
  */
 public class VaadinClient extends com.vaadin.Application {
-    private static final String OBJECT_NAME = "name";
-	private static final String OBJECT_DESCRIPTION = "description";
-    private static final long serialVersionUID = 1L;
+    public static final String OBJECT_NAME = "name";
+	public static final String OBJECT_DESCRIPTION = "description";
+
+	private static final long serialVersionUID = 1L;
     private static long SESSION_ID = 12345;
     private static String gatewayRepo = "gateway";
     private static String shopRepo = "shop";
@@ -152,12 +153,8 @@ public class VaadinClient extends com.va
     private List<ArtifactObject> m_artifacts;
     private List<GroupObject> m_features;
     private List<StatefulGatewayObject> m_targets;
-    private List<RepositoryObject> m_associatedItems = new ArrayList<RepositoryObject>();
-    private List<RepositoryObject> m_relatedItems = new ArrayList<RepositoryObject>();
+    private final Associations m_associations = new Associations();
     
-    private Table m_activeTable;
-    private Set<?> m_activeSelection;
-    public SelectionListener m_activeSelectionListener;
     private List<OBREntry> m_obrList;
     private GridLayout m_grid;
 
@@ -205,20 +202,7 @@ public class VaadinClient extends com.va
     public void init() {
         System.out.println("INIT " + this);
         
-        try {
-            User user = m_userAdmin.getUser("username", "d");
-            RepositoryAdminLoginContext context = m_admin.createLoginContext(user);
-            
-            context.addShopRepository(new URL(hostName + endpoint), customerName, shopRepo, true)
-                .setObrBase(new URL(obr))
-                .addGatewayRepository(new URL(hostName + endpoint), customerName, gatewayRepo, true)
-                .addDeploymentRepository(new URL(hostName + endpoint), customerName, deployRepo, true);
-            m_admin.login(context);
-            m_admin.checkout();
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-        }
+        login();
         
         setTheme("ace");
         final Window main = new Window("Apache ACE - User Interface - " + this);
@@ -268,10 +252,10 @@ public class VaadinClient extends com.va
         progress.setPollingInterval(500);
         m_grid.addComponent(progress, 0, 3);
 
-        m_artifactsPanel.addListener(new SelectionListener(m_artifactsPanel, m_artifactRepository, new Class[] {}, new Class[] { GroupObject.class, LicenseObject.class, GatewayObject.class }, new Table[] { m_featuresPanel, m_distributionsPanel, m_targetsPanel }));
-        m_featuresPanel.addListener(new SelectionListener(m_featuresPanel, m_featureRepository, new Class[] { ArtifactObject.class }, new Class[] { LicenseObject.class, GatewayObject.class }, new Table[] { m_artifactsPanel, m_distributionsPanel, m_targetsPanel }));
-        m_distributionsPanel.addListener(new SelectionListener(m_distributionsPanel, m_distributionRepository, new Class[] { GroupObject.class, ArtifactObject.class }, new Class[] { GatewayObject.class }, new Table[] { m_artifactsPanel, m_featuresPanel, m_targetsPanel }));
-        m_targetsPanel.addListener(new SelectionListener(m_targetsPanel, m_statefulTargetRepository, new Class[] { LicenseObject.class, GroupObject.class, ArtifactObject.class}, new Class[] {}, new Table[] { m_artifactsPanel, m_featuresPanel, m_distributionsPanel }));
+        m_artifactsPanel.addListener(m_associations.createSelectionListener(m_artifactsPanel, m_artifactRepository, new Class[] {}, new Class[] { GroupObject.class, LicenseObject.class, GatewayObject.class }, new Table[] { m_featuresPanel, m_distributionsPanel, m_targetsPanel }));
+        m_featuresPanel.addListener(m_associations.createSelectionListener(m_featuresPanel, m_featureRepository, new Class[] { ArtifactObject.class }, new Class[] { LicenseObject.class, GatewayObject.class }, new Table[] { m_artifactsPanel, m_distributionsPanel, m_targetsPanel }));
+        m_distributionsPanel.addListener(m_associations.createSelectionListener(m_distributionsPanel, m_distributionRepository, new Class[] { GroupObject.class, ArtifactObject.class }, new Class[] { GatewayObject.class }, new Table[] { m_artifactsPanel, m_featuresPanel, m_targetsPanel }));
+        m_targetsPanel.addListener(m_associations.createSelectionListener(m_targetsPanel, m_statefulTargetRepository, new Class[] { LicenseObject.class, GroupObject.class, ArtifactObject.class}, new Class[] {}, new Table[] { m_artifactsPanel, m_featuresPanel, m_distributionsPanel }));
 
         m_artifactsPanel.setDropHandler(new AssociationDropHandler((Table) null, m_featuresPanel) {
             @Override
@@ -332,22 +316,28 @@ public class VaadinClient extends com.va
 
         main.addComponent(m_grid);
         
-//        m_manager.add(m_manager.createComponent()
-//            .setInterface(EventHandler.class.getName(), new Properties() {{
-//                put(EventConstants.EVENT_TOPIC, GroupObject.TOPIC_ALL);
-//            }})
-//            .setImplementation(m_featuresTable)
-//            .add(m_manager.createServiceDependency()
-//                .setService(GroupRepository.class, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")")
-//                .setRequired(true)
-//                .setInstanceBound(true)
-//            )
-//        );
         addListener(m_artifactsPanel, ArtifactObject.TOPIC_ALL);
         addListener(m_featuresPanel, GroupObject.TOPIC_ALL);
         addListener(m_distributionsPanel, LicenseObject.TOPIC_ALL);
         addListener(m_targetsPanel, StatefulGatewayObject.TOPIC_ALL);
     }
+
+	private void login() {
+		try {
+            User user = m_userAdmin.getUser("username", "d");
+            RepositoryAdminLoginContext context = m_admin.createLoginContext(user);
+            
+            context.addShopRepository(new URL(hostName + endpoint), customerName, shopRepo, true)
+                .setObrBase(new URL(obr))
+                .addGatewayRepository(new URL(hostName + endpoint), customerName, gatewayRepo, true)
+                .addDeploymentRepository(new URL(hostName + endpoint), customerName, deployRepo, true);
+            m_admin.login(context);
+            m_admin.checkout();
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+	}
     
     private void addListener(final Object implementation, final String topic) {
         m_manager.add(m_manager.createComponent()
@@ -359,7 +349,7 @@ public class VaadinClient extends com.va
     }
 
     private GridLayout createToolbar() {
-        GridLayout toolbar = new GridLayout(3,1);
+        GridLayout toolbar = new GridLayout(3, 1);
         toolbar.setSpacing(true);
 
         Button retrieveButton = new Button("Retrieve");
@@ -411,7 +401,7 @@ public class VaadinClient extends com.va
     }
 
     private ObjectPanel createArtifactsPanel(Window main) {
-        return new ObjectPanel("Artifact", main, false, false) {
+        return new ObjectPanel(m_associations, "Artifact", main, false, false) {
             @Override
             protected RepositoryObject getFromId(String id) {
                 return getArtifact(id);
@@ -453,7 +443,7 @@ public class VaadinClient extends com.va
                             System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
                             m_artifact2GroupAssociationRepository.remove(association);
                         }
-                        m_associatedItems.remove(object);
+                        m_associations.removeAssociatedItem(object);
                         m_table.requestRepaint();
                     }
                 };
@@ -473,7 +463,7 @@ public class VaadinClient extends com.va
     }
 
     private ObjectPanel createFeaturesPanel(Window main) {
-        return new ObjectPanel("Feature", main, true, true) {
+        return new ObjectPanel(m_associations, "Feature", main, true, true) {
             @Override
             protected RepositoryObject getFromId(String id) {
                 return getFeature(id);
@@ -513,7 +503,7 @@ public class VaadinClient extends com.va
                             System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
                             m_artifact2GroupAssociationRepository.remove(association);
                         }
-                        m_associatedItems.remove(object);
+                        m_associations.removeAssociatedItem(object);
                         m_table.requestRepaint();
                     }
 
@@ -524,7 +514,7 @@ public class VaadinClient extends com.va
                             System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
                             m_group2LicenseAssociationRepository.remove(association);
                         }
-                        m_associatedItems.remove(object);
+                        m_associations.removeAssociatedItem(object);
                         m_table.requestRepaint();
                     }
                 };
@@ -543,8 +533,40 @@ public class VaadinClient extends com.va
         
     }
 
+    public abstract class RemoveLinkButton<REPO_OBJECT extends RepositoryObject> extends Button {
+        // TODO generify?
+        public RemoveLinkButton(final REPO_OBJECT object, final ObjectPanel toLeft, final ObjectPanel toRight) {
+            super("-");
+            setStyleName("small");
+            addListener(new Button.ClickListener() {
+                public void buttonClick(ClickEvent event) {
+                    Set<?> selection = m_associations.getActiveSelection();
+                    if (selection != null) {
+	                    if (m_associations.isActiveTable(toLeft)) {
+                            for (Object item : selection) {
+                                RepositoryObject selected = m_associations.lookupInActiveSelection(item);
+                                removeLinkFromLeft(object, selected);
+                            }
+	                    }
+	                    else if (m_associations.isActiveTable(toRight)) {
+                            for (Object item : selection) {
+                                RepositoryObject selected = m_associations.lookupInActiveSelection(item);
+                                removeLinkFromRight(object, selected);
+                            }
+	                    }
+                    }
+                }
+            });
+        }
+
+        protected abstract void removeLinkFromLeft(REPO_OBJECT object, RepositoryObject other);
+
+        protected abstract void removeLinkFromRight(REPO_OBJECT object, RepositoryObject other);
+    }
+    
+    
     private ObjectPanel createDistributionsPanel(Window main) {
-        return new ObjectPanel("Distribution", main, true, true) {
+        return new ObjectPanel(m_associations, "Distribution", main, true, true) {
             @Override
             protected RepositoryObject getFromId(String id) {
                 return getDistribution(id);
@@ -583,7 +605,7 @@ public class VaadinClient extends com.va
                             System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
                             m_group2LicenseAssociationRepository.remove(association);
                         }
-                        m_associatedItems.remove(object);
+                        m_associations.removeAssociatedItem(object);
                         m_table.requestRepaint();
                     }
 
@@ -594,7 +616,7 @@ public class VaadinClient extends com.va
                             System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
                             m_license2GatewayAssociationRepository.remove(association);
                         }
-                        m_associatedItems.remove(object);
+                        m_associations.removeAssociatedItem(object);
                         m_table.requestRepaint();
                     }
                 };
@@ -613,7 +635,7 @@ public class VaadinClient extends com.va
     }
 
     private ObjectPanel createTargetsPanel(Window main) {
-        return new ObjectPanel("Target", main, false, false) {
+        return new ObjectPanel(m_associations, "Target", main, false, false) {
             @Override
             protected RepositoryObject getFromId(String id) {
                 return getTarget(id);
@@ -667,7 +689,7 @@ public class VaadinClient extends com.va
                             System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
                             m_license2GatewayAssociationRepository.remove(association);
                         }
-                        m_associatedItems.remove(object);
+                        m_associations.removeAssociatedItem(object);
                         m_table.requestRepaint();
                     }
 
@@ -713,7 +735,9 @@ public class VaadinClient extends com.va
                 Object fromItemId = tt.getItemId();
                 System.out.println("FF: " + fromItemId);
                 // get the active selection, but only if we drag from the same table
-                Set<?> selection = (tt.getSourceComponent().equals(m_activeTable)) ? m_activeSelection : null;
+                
+                Set<?> selection = m_associations.isActiveTable(tt.getSourceComponent()) ? m_associations.getActiveSelection() : null;
+                
                 System.out.println("T: " + targetDetails.getClass().getName());
                 if (targetDetails instanceof AbstractSelectTargetDetails) {
                     AbstractSelectTargetDetails ttd = (AbstractSelectTargetDetails) targetDetails;
@@ -757,7 +781,7 @@ public class VaadinClient extends com.va
         protected abstract void associateFromRight(String left, String right);
     }
 
-    private void showEditWindow(String objectName, final NamedObject object, Window main) {
+    private static void showEditWindow(String objectName, final NamedObject object, Window main) {
         final Window featureWindow = new Window();
         featureWindow.setModal(true);
         featureWindow.setCaption("Edit " + objectName);
@@ -824,10 +848,9 @@ public class VaadinClient extends com.va
         return button;
     }
 
-    private class AddFeatureWindow extends AddWindow {
+    private class AddFeatureWindow extends AbstractAddWindow {
         public AddFeatureWindow(Window main) {
-            super(main);
-            setCaption("Add Feature");
+            super(main, "Add Feature");
         }
 
         @Override
@@ -837,10 +860,9 @@ public class VaadinClient extends com.va
 
     }
 
-    private class AddDistributionWindow extends AddWindow {
+    private class AddDistributionWindow extends AbstractAddWindow {
         public AddDistributionWindow(Window main) {
-            super(main);
-            setCaption("Add Distribution");
+            super(main, "Add Distribution");
         }
 
         @Override
@@ -849,10 +871,9 @@ public class VaadinClient extends com.va
         }
     }
     
-    private class AddTargetWindow extends AddWindow {
+    private class AddTargetWindow extends AbstractAddWindow {
         public AddTargetWindow(Window main) {
-            super(main);
-            setCaption("Add Target");
+            super(main, "Add Target");
         }
 
         @Override
@@ -861,61 +882,6 @@ public class VaadinClient extends com.va
         }
     }
 
-    private abstract class AddWindow extends Window {
-        private final Window m_main;
-        private final TextField m_name;
-
-        public AddWindow(final Window main) {
-            m_main = main;
-            setModal(true);
-            setWidth("15em");
-
-            // Configure the windws layout; by default a VerticalLayout
-            VerticalLayout layout = (VerticalLayout) getContent();
-            layout.setMargin(true);
-            layout.setSpacing(true);
-
-            m_name = new TextField("name");
-            final TextField description = new TextField("description");
-
-            layout.addComponent(m_name);
-            layout.addComponent(description);
-
-            Button close = new Button("Ok", new Button.ClickListener() {
-                // inline click-listener
-                public void buttonClick(ClickEvent event) {
-                    // close the window by removing it from the parent window
-                    (getParent()).removeWindow(AddWindow.this);
-                    // create the feature
-                    create((String) m_name.getValue(), (String) description.getValue());
-                }
-            });
-            // The components added to the window are actually added to the window's
-            // layout; you can use either. Alignments are set using the layout
-            layout.addComponent(close);
-            layout.setComponentAlignment(close, "right");
-        }
-
-        public void show() {
-            if (getParent() != null) {
-                // window is already showing
-                m_main.getWindow().showNotification(
-                        "Window is already open");
-            } else {
-                // Open the subwindow by adding it to the parent
-                // window
-                m_main.getWindow().addWindow(this);
-            }
-            setRelevantFocus();
-        }
-
-        private void setRelevantFocus() {
-            m_name.focus();
-        }
-
-        protected abstract void create(String name, String description);
-    }
-
     private void createFeature(String name, String description) {
         Map<String, String> attributes = new HashMap<String, String>();
         attributes.put(GroupObject.KEY_NAME, name);
@@ -997,26 +963,6 @@ public class VaadinClient extends com.va
         Map<String, String> tags = new HashMap<String, String>();
         m_distributionRepository.create(attributes, tags);
     }
-    
-    /**
-     * Helper method to find all related {@link RepositoryObject}s in a given 'direction'
-     */
-    private <FROM extends RepositoryObject, TO extends RepositoryObject> List<TO> getRelated(FROM from, Class<TO> toClass) {
-        // if the SGO is not backed by a GO yet, this will cause an exception
-        return from.getAssociations(toClass);
-    }
-    
-    /**
-     * Helper method to find all related {@link RepositoryObject}s in a given 'direction', starting with a list of objects
-     */
-    private <FROM extends RepositoryObject, TO extends RepositoryObject> List<TO> getRelated(List<FROM> from, Class<TO> toClass) {
-        List<TO> result = new ArrayList<TO>();
-        for (RepositoryObject o : from) {
-            result.addAll(getRelated(o, toClass));
-        }
-        return result;
-    }
-
 
     private void updateTableData() {
         m_artifactsPanel.populate();
@@ -1025,173 +971,6 @@ public class VaadinClient extends com.va
         m_targetsPanel.populate();
     }
     
-    // TODO rip the button logic from this method
-    private void updateTableDataX() {
-        m_artifacts = m_artifactRepository.get();
-        m_artifactsPanel.removeAllItems();
-        for (ArtifactObject artifact : m_artifacts) {
-            Item item = m_artifactsPanel.addItem(artifact.getName());
-            item.getItemProperty(OBJECT_NAME).setValue(artifact.getName());
-            item.getItemProperty(OBJECT_DESCRIPTION).setValue(artifact.getDescription());
-            Button removeLinkButton = new RemoveLinkButton<ArtifactObject>(artifact, null, m_featuresPanel) {
-                @Override
-                protected void removeLinkFromLeft(ArtifactObject object, RepositoryObject other) {}
-
-                @Override
-                protected void removeLinkFromRight(ArtifactObject object, RepositoryObject other) {
-                    List<Artifact2GroupAssociation> associations = object.getAssociationsWith((GroupObject) other);
-                    for (Artifact2GroupAssociation association : associations) {
-                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-                        m_artifact2GroupAssociationRepository.remove(association);
-                    }
-                    m_associatedItems.remove(object);
-                }
-            }; // add this to the others
-            item.getItemProperty("button").setValue(removeLinkButton);
-        }
-        m_features = m_featureRepository.get();
-        m_featuresPanel.removeAllItems();
-        for (GroupObject group : m_features) {
-            Item featureItem = m_featuresPanel.addItem(group.getName());
-            featureItem.getItemProperty(OBJECT_NAME).setValue(group.getName());
-            featureItem.getItemProperty(OBJECT_DESCRIPTION).setValue(group.getDescription());
-            Button removeLinkButton = new RemoveLinkButton<GroupObject>(group, m_artifactsPanel, m_distributionsPanel) {
-                @Override
-                protected void removeLinkFromLeft(GroupObject object, RepositoryObject other) {
-                    List<Artifact2GroupAssociation> associations = object.getAssociationsWith((ArtifactObject) other);
-                    for (Artifact2GroupAssociation association : associations) {
-                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-                        m_artifact2GroupAssociationRepository.remove(association);
-                    }
-                    m_associatedItems.remove(object);
-                }
-
-                @Override
-                protected void removeLinkFromRight(GroupObject object, RepositoryObject other) {
-                    List<Group2LicenseAssociation> associations = object.getAssociationsWith((LicenseObject) other);
-                    for (Group2LicenseAssociation association : associations) {
-                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-                        m_group2LicenseAssociationRepository.remove(association);
-                    }
-                    m_associatedItems.remove(object);
-                }
-            }; // add this to the others
-            featureItem.getItemProperty("button").setValue(removeLinkButton);
-        }
-        m_distributions = m_distributionRepository.get();
-        m_distributionsPanel.removeAllItems();
-        for (final LicenseObject license : m_distributions) {
-            Item licenseItem = m_distributionsPanel.addItem(license.getName());
-            licenseItem.getItemProperty(OBJECT_NAME).setValue(license.getName());
-            licenseItem.getItemProperty(OBJECT_DESCRIPTION).setValue(license.getDescription());
-            Button removeLinkButton = new RemoveLinkButton<LicenseObject>(license, m_featuresPanel, m_targetsPanel) {
-                @Override
-                protected void removeLinkFromLeft(LicenseObject object, RepositoryObject other) {
-                    List<Group2LicenseAssociation> associations = object.getAssociationsWith((GroupObject) other);
-                    for (Group2LicenseAssociation association : associations) {
-                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-                        m_group2LicenseAssociationRepository.remove(association);
-                    }
-                    m_associatedItems.remove(object);
-                }
-
-                @Override
-                protected void removeLinkFromRight(LicenseObject object, RepositoryObject other) {
-                    List<License2GatewayAssociation> associations = object.getAssociationsWith((GatewayObject) other);
-                    for (License2GatewayAssociation association : associations) {
-                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-                        m_license2GatewayAssociationRepository.remove(association);
-                    }
-                    m_associatedItems.remove(object);
-                }
-            }; // add this to the others
-            licenseItem.getItemProperty("button").setValue(removeLinkButton);
-        }
-        m_statefulTargetRepository.refresh();
-        m_targets = m_statefulTargetRepository.get();
-        m_targetsPanel.removeAllItems();
-        for (StatefulGatewayObject target : m_targets) {
-            Item targetItem = m_targetsPanel.addItem(target.getID());
-            targetItem.getItemProperty(OBJECT_NAME).setValue(target.getID());
-            targetItem.getItemProperty(OBJECT_DESCRIPTION).setValue("?");
-            Button removeLinkButton = new RemoveLinkButton<StatefulGatewayObject>(target, m_distributionsPanel, null) {
-                @Override
-                protected void removeLinkFromLeft(StatefulGatewayObject object, RepositoryObject other) {
-                    List<License2GatewayAssociation> associations = object.getAssociationsWith((LicenseObject) other);
-                    for (License2GatewayAssociation association : associations) {
-                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-                        m_license2GatewayAssociationRepository.remove(association);
-                    }
-                    m_associatedItems.remove(object);
-                }
-
-                @Override
-                protected void removeLinkFromRight(StatefulGatewayObject object, RepositoryObject other) {
-                }
-            }; // add this to the others
-            targetItem.getItemProperty("button").setValue(removeLinkButton);
-        }
-        
-//        m_targets = m_targetRepository.get();
-//        m_targetsPanel.removeAllItems();
-//        for (GatewayObject license : m_targets) {
-//            Item targetItem = m_targetsPanel.addItem(license.getID());
-//            targetItem.getItemProperty(OBJECT_NAME).setValue(license.getID());
-//            targetItem.getItemProperty(OBJECT_DESCRIPTION).setValue("?");
-//            Button removeLinkButton = new RemoveLinkButton<GatewayObject>(license, m_distributionsPanel, null) {
-//                @Override
-//                protected void removeLinkFromLeft(GatewayObject object, RepositoryObject other) {
-//                    List<License2GatewayAssociation> associations = object.getAssociationsWith((LicenseObject) other);
-//                    for (License2GatewayAssociation association : associations) {
-//                        System.out.println("> " + association.getLeft() + " <-> " + association.getRight());
-//                        m_license2GatewayAssociationRepository.remove(association);
-//                    }
-//                    m_associatedItems.remove(object);
-//                }
-//
-//                @Override
-//                protected void removeLinkFromRight(GatewayObject object, RepositoryObject other) {
-//                }
-//            }; // add this to the others
-//            targetItem.getItemProperty("button").setValue(removeLinkButton);
-//        }
-    }
-
-    private abstract class RemoveLinkButton<REPO_OBJECT extends RepositoryObject> extends Button {
-        // TODO generify?
-        public RemoveLinkButton(final REPO_OBJECT object, final ObjectPanel toLeft, final ObjectPanel toRight) {
-            super("-");
-            setStyleName("small");
-            addListener(new Button.ClickListener() {
-                public void buttonClick(ClickEvent event) {
-                    if (m_activeTable.equals(toLeft)) {
-                        Set<?> selection = m_activeSelection;
-                        if (selection != null) {
-                            for (Object item : selection) {
-                                RepositoryObject selected = m_activeSelectionListener.lookup(item);
-                                removeLinkFromLeft(object, selected);
-                            }
-//                            updateTableData();
-                        }
-                    }
-                    else if (m_activeTable.equals(toRight)) {
-                        Set<?> selection = m_activeSelection;
-                        if (selection != null) {
-                            for (Object item : selection) {
-                                RepositoryObject selected = m_activeSelectionListener.lookup(item);
-                                removeLinkFromRight(object, selected);
-                            }
-//                            updateTableData();
-                        }
-                    }
-                }
-            });
-        }
-
-        protected abstract void removeLinkFromLeft(REPO_OBJECT object, RepositoryObject other);
-
-        protected abstract void removeLinkFromRight(REPO_OBJECT object, RepositoryObject other);
-    }
 
     @Override
     public void close() {
@@ -1200,216 +979,20 @@ public class VaadinClient extends com.va
         // TODO: clean up the ace client session?
     }
 
-    public class SelectionListener implements Table.ValueChangeListener {
-        private final Table m_table;
-        private final Table[] m_tablesToRefresh;
-        private final ObjectRepository<? extends RepositoryObject> m_repository;
-        private final Class[] m_left;
-        private final Class[] m_right;
-        
-        public SelectionListener(Table table, ObjectRepository<? extends RepositoryObject> repository, Class[] left, Class[] right, Table[] tablesToRefresh) {
-            m_table = table;
-            m_repository = repository;
-            m_left = left;
-            m_right = right;
-            m_tablesToRefresh = tablesToRefresh;
-        }
-        
-        public void valueChange(ValueChangeEvent event) {
-            
-            if (m_activeSelection != null && m_activeTable != null) {
-                if (m_activeTable.equals(m_table)) {
-                    System.out.println("SAME TABLE!");
-                }
-                else {
-                    for (Object val : m_activeSelection) {
-                        m_activeTable.unselect(val);
-                    }
-                    m_table.requestRepaint();
-                }
-            }
-            
-            m_activeSelectionListener = this;
-            
-            // set the active table
-            m_activeTable = m_table;
-            
-            // in multiselect mode, a Set of itemIds is returned,
-            // in singleselect mode the itemId is returned directly
-            Set<?> value = (Set<?>) event.getProperty().getValue();
-            if (null == value || value.size() == 0) {
-//                    selected.setValue("No selection");
-            } else {
-//                    selected.setValue("Selected: " + table.getValue());
-            }
-
-            // remember the active selection too
-            m_activeSelection = value;
 
-            if (value == null) {
-                System.out.println("no selection");
-            }
-            else {
-                System.out.println("selection:");
-                
-                m_associatedItems.clear();
-                m_relatedItems.clear();
-                for (Object val : value) {
-                    System.out.println(" - " + m_table.getItem(val).getItemProperty(OBJECT_NAME) + " " + val);
-                    RepositoryObject lo = lookup(val);
-                    System.out.println("lookup(" + val + ") returned " + lo);
-                    if (lo != null) {
-                        List related = null;
-                        for (int i = 0; i < m_left.length; i++) {
-                            if (i == 0) {
-                                related = getRelated(lo, m_left[i]);
-                                System.out.println("left associated:");
-                                for (Object o : related) {
-                                    System.out.println(" -> " + o);
-                                }
-                                m_associatedItems.addAll(related);
-                            }
-                            else {
-                                related = getRelated(related, m_left[i]);
-                                System.out.println("left related:");
-                                for (Object o : related) {
-                                    System.out.println(" -> " + o);
-                                }
-                                m_relatedItems.addAll(related);
-                            }
-                        }
-                        for (int i = 0; i < m_right.length; i++) {
-                            if (i == 0) {
-                                related = getRelated(lo, m_right[i]);
-                                System.out.println("right associated:");
-                                for (Object o : related) {
-                                    System.out.println(" -> " + o);
-                                }
-                                m_associatedItems.addAll(related);
-                            }
-                            else {
-                                related = getRelated(related, m_right[i]);
-                                System.out.println("right related:");
-                                for (Object o : related) {
-                                    System.out.println(" -> " + o);
-                                }
-                                m_relatedItems.addAll(related);
-                            }
-                        }
-                    }
-                    System.out.println("summarizing associated:");
-                    for (RepositoryObject ro : m_associatedItems) {
-                        System.out.println("** " + ro);
-                    }
-                    System.out.println("summarizing related:");
-                    for (RepositoryObject ro : m_relatedItems) {
-                        System.out.println("** " + ro);
-                    }
-                    
-                    for (Table t : m_tablesToRefresh) {
-                        System.out.println("refreshing " + t);
-                        t.requestRepaint();
-                    }
-                    
-                    System.out.println("summarizing associated:");
-                    for (RepositoryObject ro : m_associatedItems) {
-                        System.out.println("** " + ro);
-                    }
-                    System.out.println("summarizing related:");
-                    for (RepositoryObject ro : m_relatedItems) {
-                        System.out.println("** " + ro);
-                    }
-                    
-//                    // when switching columns, we need to repaint, but it messes up the
-//                    // cursor position
-//                    m_table.requestRepaint();
-                }
-            }
-        }
-
-        public RepositoryObject lookup(Object value) {
-            for (RepositoryObject object : m_repository.get()) {
-                System.out.println("..." + object);
-                if (object instanceof StatefulGatewayObject) {
-                    StatefulGatewayObject sgo = (StatefulGatewayObject) object;
-                    if (sgo.isRegistered()) {
-                        object = sgo.getGatewayObject();
-                    }
-                    else {
-                        object = null;
-                    }
-                }
-                if (object != null) {
-                    NamedObject namedObject = getNamedObject(object);
-                    System.out.println("..." + namedObject);
-                    if (namedObject != null) {
-                        if (namedObject.getName().equals(value)) {
-                            System.out.println("Found: " + namedObject.getName());
-                            return object;
-                        }
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    /** Highlights associated and related items in other columns. */
-    private abstract class CellStyleGeneratorImplementation implements CellStyleGenerator {
-        public String getStyle(Object itemId, Object propertyId) {
-            if (propertyId == null) {
-                // no propertyId, styling row
-                for (RepositoryObject o : m_associatedItems) {
-                    System.out.println("cellrenderer probing: " + o);
-                    if (equals(itemId, o)) {
-                        System.out.println(" -> associated");
-                        return "associated";
-                    }
-                }
-                for (RepositoryObject o : m_relatedItems) {
-                    if (equals(itemId, o)) {
-                        System.out.println(" -> related");
-                        return "related";
-                    }
-                }
-                System.out.println("cellrenderer: unrelated");
-            }
-            return null;
-        }
-        public abstract boolean equals(Object itemId, RepositoryObject object);
-    }
-
-    private NamedObject getNamedObject(RepositoryObject object) {
-        if (object instanceof ArtifactObject) {
-            return new NamedArtifactObject((ArtifactObject) object);
-        }
-        else if (object instanceof GroupObject) {
-            return new NamedFeatureObject((GroupObject) object);
-        }
-        else if (object instanceof LicenseObject) {
-            return new NamedDistributionObject((LicenseObject) object);
-        }
-        else if (object instanceof GatewayObject) {
-            return new NamedTargetObject((GatewayObject) object);
-        }
-        return null;
-    }
-
-    private abstract class ObjectPanel extends Table implements EventHandler {
+    public abstract class ObjectPanel extends Table implements EventHandler {
         public static final String ACTIONS = "actions";
         protected Table m_table = this;
-        public ObjectPanel(final String name, final Window main, boolean hasEdit, boolean hasDeleteButton) {
+        protected Associations m_associations;
+        
+        public ObjectPanel(Associations associations, final String name, final Window main, boolean hasEdit, boolean hasDeleteButton) {
             super(name + "s");
+            m_associations = associations;
             addContainerProperty(OBJECT_NAME, String.class, null);
             addContainerProperty(OBJECT_DESCRIPTION, String.class, null);
             addContainerProperty(ACTIONS, HorizontalLayout.class, null);
             setSizeFull();
-            setCellStyleGenerator(new CellStyleGeneratorImplementation() {
-                @Override
-                public boolean equals(Object itemId, RepositoryObject object) {
-                    return (getNamedObject(object).getName().equals(itemId));
-                }
-            });
+            setCellStyleGenerator(m_associations.createCellStyleGenerator());
             setSelectable(true);
             setMultiSelect(true);
             setImmediate(true);
@@ -1420,7 +1003,7 @@ public class VaadinClient extends com.va
                         if (event.isDoubleClick()) {
                             String itemId = (String) event.getItemId();
                             RepositoryObject object = getFromId(itemId);
-                            showEditWindow(name, getNamedObject(object), main);
+                            showEditWindow(name, m_associations.getNamedObject(object), main);
                         }
                     }
                 });
@@ -1430,95 +1013,9 @@ public class VaadinClient extends com.va
         protected abstract RepositoryObject getFromId(String id);
     }
 
-    private interface NamedObject {
-        String getName();
-        String getDescription();
-        void setDescription(String description);
-    }
-
-    private static class NamedArtifactObject implements NamedObject {
-        private final ArtifactObject m_target;
-
-        public NamedArtifactObject(ArtifactObject target) {
-            m_target = target;
-        }
-
-        public String getName() {
-            return m_target.getName();
-        }
-
-        public String getDescription() {
-            return m_target.getDescription();
-        }
-
-        public void setDescription(String description) {
-            m_target.setDescription(description);
-        }
-    }
-
-    private static class NamedFeatureObject implements NamedObject {
-        private final GroupObject m_target;
-
-        public NamedFeatureObject(GroupObject target) {
-            m_target = target;
-        }
-
-        public String getName() {
-            return m_target.getName();
-        }
-
-        public String getDescription() {
-            return m_target.getDescription();
-        }
-
-        public void setDescription(String description) {
-            m_target.setDescription(description);
-        }
-    }
-
-    private static class NamedDistributionObject implements NamedObject {
-        private final LicenseObject m_target;
-
-        public NamedDistributionObject(LicenseObject target) {
-            m_target = target;
-        }
-
-        public String getName() {
-            return m_target.getName();
-        }
-
-        public String getDescription() {
-            return m_target.getDescription();
-        }
-
-        public void setDescription(String description) {
-            m_target.setDescription(description);
-        }
-    }
-
-    private static class NamedTargetObject implements NamedObject {
-        private final GatewayObject m_target;
-
-        public NamedTargetObject(GatewayObject target) {
-            m_target = target;
-        }
-
-        public String getName() {
-            return m_target.getID();
-        }
-
-        public String getDescription() {
-            return "";
-        }
-
-        public void setDescription(String description) {
-            throw new IllegalArgumentException();
-        }
-    }
-    
     private class AddArtifactWindow extends Window {
     	private File m_file;
-    	private List<URL> m_uploadedArtifacts = new ArrayList<URL>();
+    	private List<File> m_uploadedArtifacts = new ArrayList<File>();
     	
     	public AddArtifactWindow(final Window main) {
     		super();
@@ -1539,6 +1036,11 @@ public class VaadinClient extends com.va
     				FileOutputStream fos = null; // Output stream to write to
     		        try {
     		        	m_file = new File(filename); //File.createTempFile(filename, "tmp");
+    		        	if (m_file.exists()) {
+    		        		throw new IOException("Uploaded file already exists.");
+    		        		// meaning probably somebody else is in the process of uploading 
+    		        		// the exact same file...
+    		        	}
     		            // Open the file for writing.
     		            fos = new FileOutputStream(m_file);
     		        }
@@ -1574,7 +1076,7 @@ public class VaadinClient extends com.va
     		            Item item = uploadedArtifacts.addItem(artifact);
     		            item.getItemProperty("symbolic name").setValue(m_file.getName());
     		            item.getItemProperty("version").setValue("");
-    					m_uploadedArtifacts.add(artifact);
+    					m_uploadedArtifacts.add(m_file);
 					}
     				catch (IOException e) {
 						// TODO Auto-generated catch block
@@ -1619,14 +1121,17 @@ public class VaadinClient extends com.va
                             }
                         }
                     }
-                    for (URL artifact : m_uploadedArtifacts) {
+                    for (File artifact : m_uploadedArtifacts) {
                     	try {
-                    		ArtifactObject ao = importBundle(artifact);
+                    		ArtifactObject ao = importBundle(artifact.toURI().toURL());
                             added.add(ao);
 						}
                     	catch (IOException e) {
 							e.printStackTrace();
 						}
+                    	finally {
+                    		artifact.delete();
+                    	}
                     }
                     // TODO: make a decision here
                     // so now we have enough information to show a list of imported artifacts (added)
@@ -1655,18 +1160,6 @@ public class VaadinClient extends com.va
         }
     }
     
-    public static class ArtifactTable extends Table {
-        public ArtifactTable(final Window main) {
-            super("Artifacts");
-            addContainerProperty("symbolic name", String.class, null);
-            addContainerProperty("version", String.class, null);
-            setSizeFull();
-            setSelectable(true);
-            setMultiSelect(true);
-            setImmediate(true);
-        }
-    }
-    
     public void getBundles(Table table) throws Exception {
         getBundles(table, "http://localhost:8080/obr/");
     }
@@ -1761,38 +1254,4 @@ public class VaadinClient extends com.va
     public ArtifactObject importBundle(URL artifact) throws IOException {
 		return m_artifactRepository.importArtifact(artifact, true);
     }
-    
-    public static class OBREntry {
-        private final String m_symbolicName;
-        private final String m_version;
-        private final String m_uri;
-        
-        public OBREntry(String symbolicName, String version, String uri) {
-            m_symbolicName = symbolicName;
-            m_version = version;
-            m_uri = uri;
-        }
-        
-        public String getVersion() {
-            return m_version;
-        }
-        
-        public String getSymbolicName() {
-            return m_symbolicName;
-        }
-        
-        public String getUri() {
-            return m_uri;
-        }
-
-        @Override
-        public int hashCode() {
-            return m_uri.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return m_uri.equals(((OBREntry) obj).m_uri);
-        }
-    }
-}
\ No newline at end of file
+}