ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r794436 - in /incubator/ace/trunk/webui: src/org/apache/ace/client/ src/org/apache/ace/client/services/ src/org/apache/ace/server/ war/
Date Wed, 15 Jul 2009 22:16:11 GMT
Author: marrs
Date: Wed Jul 15 22:16:11 2009
New Revision: 794436

URL: http://svn.apache.org/viewvc?rev=794436&view=rev
Log:
ACE-30 and ACE-31 combined patch applied

Added:
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/Descriptor.java   (with props)
    incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectMapping.java   (with props)
    incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectServiceImpl.java   (with props)
Modified:
    incubator/ace/trunk/webui/src/org/apache/ace/client/AddBundleDialog.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/BundleTable.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/GroupTable.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/LicenseTable.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/Main.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/ObjectTable.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/TargetTable.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationService.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationServiceAsync.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleDescriptor.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleService.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleServiceAsync.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupDescriptor.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupService.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupServiceAsync.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseDescriptor.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseService.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseServiceAsync.java
    incubator/ace/trunk/webui/src/org/apache/ace/client/services/TargetDescriptor.java
    incubator/ace/trunk/webui/src/org/apache/ace/server/AssociationServiceImpl.java
    incubator/ace/trunk/webui/src/org/apache/ace/server/BundleServiceImpl.java
    incubator/ace/trunk/webui/src/org/apache/ace/server/GroupServiceImpl.java
    incubator/ace/trunk/webui/src/org/apache/ace/server/LicenseServiceImpl.java
    incubator/ace/trunk/webui/src/org/apache/ace/server/TargetServiceImpl.java
    incubator/ace/trunk/webui/war/webui.css
    incubator/ace/trunk/webui/war/webui.html

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/AddBundleDialog.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/AddBundleDialog.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/AddBundleDialog.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/AddBundleDialog.java Wed Jul 15 22:16:11 2009
@@ -49,7 +49,7 @@
     
     OBRServiceAsync m_obrService = GWT.create(OBRService.class);
 
-    AddBundleDialog() {
+    AddBundleDialog(final Main main) {
         setText("Add bundle");
         
         final ObjectListBox<OBRBundleDescriptor> obrFiles = new ObjectListBox<OBRBundleDescriptor>();
@@ -82,7 +82,7 @@
                         Window.alert("Error importing bundle " + obrFiles.getSelectedObject());
                     }
                     public void onSuccess(Void result) {
-                        // Hurrah!
+                        main.updateUI();
                     }
                     
                 });

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/BundleTable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/BundleTable.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/BundleTable.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/BundleTable.java Wed Jul 15 22:16:11 2009
@@ -32,12 +32,12 @@
 public class BundleTable extends ObjectTable<BundleDescriptor> {
     private BundleServiceAsync m_bundleService = GWT.create(BundleService.class);
 
-    BundleTable(StatusHandler handler) {
-        super(handler);
+    BundleTable(StatusHandler handler, Main main) {
+        super(handler, main);
     }
 
     @Override
-    protected void callService(AsyncCallback<BundleDescriptor[]> callback) {
+    protected void getDescriptors(AsyncCallback<BundleDescriptor[]> callback) {
         m_bundleService.getBundles(callback);
     }
 
@@ -50,4 +50,9 @@
     protected String getTableID() {
         return "bundles";
     }
+
+    @Override
+    protected void remove(BundleDescriptor object, AsyncCallback<Void> callback) {
+        m_bundleService.remove(object, callback);
+    }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/GroupTable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/GroupTable.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/GroupTable.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/GroupTable.java Wed Jul 15 22:16:11 2009
@@ -33,12 +33,12 @@
 public class GroupTable extends ObjectTable<GroupDescriptor> {
     private GroupServiceAsync m_groupService = GWT.create(GroupService.class);
 
-    GroupTable(StatusHandler handler) {
-        super(handler);
+    GroupTable(StatusHandler handler, Main main) {
+        super(handler, main);
     }
 
     @Override
-    protected void callService(AsyncCallback<GroupDescriptor[]> callback) {
+    protected void getDescriptors(AsyncCallback<GroupDescriptor[]> callback) {
         m_groupService.getGroups(callback);
     }
 
@@ -54,11 +54,9 @@
                 public void onFailure(Throwable caught) {
                     Window.alert("Error adding group.");
                 }
-
                 public void onSuccess(Void result) {
                     // Hurrah!
                 }
-                
             });
         }
     }
@@ -68,5 +66,9 @@
         return "groups";
     }
 
+    @Override
+    protected void remove(GroupDescriptor object, AsyncCallback<Void> callback) {
+        m_groupService.remove(object, callback);
+    }
 
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/LicenseTable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/LicenseTable.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/LicenseTable.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/LicenseTable.java Wed Jul 15 22:16:11 2009
@@ -33,12 +33,12 @@
 public class LicenseTable extends ObjectTable<LicenseDescriptor> {
     private LicenseServiceAsync m_licenseService = GWT.create(LicenseService.class);
 
-    LicenseTable(StatusHandler handler) {
-        super(handler);
+    LicenseTable(StatusHandler handler, Main main) {
+        super(handler, main);
     }
 
     @Override
-    protected void callService(AsyncCallback<LicenseDescriptor[]> callback) {
+    protected void getDescriptors(AsyncCallback<LicenseDescriptor[]> callback) {
         m_licenseService.getLicenses(callback);
     }
 
@@ -54,11 +54,9 @@
                 public void onFailure(Throwable caught) {
                     Window.alert("Error adding license.");
                 }
-
                 public void onSuccess(Void result) {
                     // Hurrah!
                 }
-                
             });
         }
     }
@@ -67,4 +65,9 @@
     protected String getTableID() {
         return "licenses";
     }
+
+    @Override
+    protected void remove(LicenseDescriptor object, AsyncCallback<Void> callback) {
+        m_licenseService.remove(object, callback);
+    }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/Main.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/Main.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/Main.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/Main.java Wed Jul 15 22:16:11 2009
@@ -18,11 +18,14 @@
  */
 package org.apache.ace.client;
 
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.ace.client.services.AssociationService;
 import org.apache.ace.client.services.AssociationServiceAsync;
+import org.apache.ace.client.services.Descriptor;
 
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.core.client.GWT;
@@ -43,10 +46,10 @@
 public class Main implements EntryPoint {
     private static final int REFRESH_INTERVAL = 2000;
     private StatusLabel m_statusLabel = new StatusLabel();
-    private BundleTable m_bundleTable = new BundleTable(m_statusLabel);
-    private GroupTable m_groupTable = new GroupTable(m_statusLabel);
-    private LicenseTable m_licenseTable = new LicenseTable(m_statusLabel);
-    private TargetTable m_targetTable = new TargetTable(m_statusLabel);
+    private BundleTable m_bundleTable = new BundleTable(m_statusLabel, this);
+    private GroupTable m_groupTable = new GroupTable(m_statusLabel, this);
+    private LicenseTable m_licenseTable = new LicenseTable(m_statusLabel, this);
+    private TargetTable m_targetTable = new TargetTable(m_statusLabel, this);
     
     AssociationServiceAsync m_assocationService = GWT.create(AssociationService.class);
     
@@ -69,7 +72,7 @@
         RootPanel.get("bundlesHeader").add(addBundleButton);
         addBundleButton.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
-                new AddBundleDialog().show();
+                new AddBundleDialog(Main.this).show();
             }
         });
 
@@ -112,15 +115,14 @@
         // Create the association buttons
         Button b2g = new Button("<->");
         RootPanel.get("b2gButton").add(b2g);
-        
         b2g.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
-                m_assocationService.link(m_bundleTable.getSelectedObject(), m_groupTable.getSelectedObject(), new AsyncCallback<Void>() {
+                m_assocationService.link(m_bundleTable.getCheckedObject(), m_groupTable.getCheckedObject(), new AsyncCallback<Void>() {
                     public void onFailure(Throwable caught) {
                         Window.alert("Error creating association");
                     }
                     public void onSuccess(Void result) {
-                        // Hurrah!
+                        updateHighlight();
                     }
                 });
             }
@@ -130,12 +132,12 @@
         RootPanel.get("g2lButton").add(g2l);
         g2l.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
-                m_assocationService.link(m_groupTable.getSelectedObject(), m_licenseTable.getSelectedObject(), new AsyncCallback<Void>() {
+                m_assocationService.link(m_groupTable.getCheckedObject(), m_licenseTable.getCheckedObject(), new AsyncCallback<Void>() {
                     public void onFailure(Throwable caught) {
                         Window.alert("Error creating association");
                     }
                     public void onSuccess(Void result) {
-                        // Hurrah!
+                        updateHighlight();
                     }
                 });
             }
@@ -144,12 +146,12 @@
         RootPanel.get("l2tButton").add(l2t);
         l2t.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
-                m_assocationService.link(m_licenseTable.getSelectedObject(), m_targetTable.getSelectedObject(), new AsyncCallback<Void>() {
+                m_assocationService.link(m_licenseTable.getCheckedObject(), m_targetTable.getCheckedObject(), new AsyncCallback<Void>() {
                     public void onFailure(Throwable caught) {
                         Window.alert("Error creating association");
                     }
                     public void onSuccess(Void result) {
-                        // Hurrah!
+                        updateHighlight();
                     }
                 });
             }
@@ -182,12 +184,70 @@
     }
     
     /**
+     * Triggers the updating of the highlight
+     */
+    void updateHighlight() {
+        m_assocationService.getRelated(getSelectedObject(), new AsyncCallback<Descriptor[]>() {
+            public void onFailure(Throwable caught) {
+                // Too bad...
+            }
+            public void onSuccess(Descriptor[] result) {
+                highlight(Arrays.asList(result));
+            }
+        });
+    }
+    
+    /**
+     * Helper method to delegate the highlights to the tables.
+     */
+    private void highlight(List<Descriptor> descriptors) {
+        m_bundleTable.highlight(descriptors);
+        m_groupTable.highlight(descriptors);
+        m_licenseTable.highlight(descriptors);
+        m_targetTable.highlight(descriptors);
+    }
+    
+    /**
+     * Finds the currently selected object; if no object is selected, <code>null</code> will be returned.
+     */
+    Descriptor getSelectedObject() {
+        if (m_bundleTable.getSelectedObject() != null) {
+            return m_bundleTable.getSelectedObject();
+        }
+        else if (m_groupTable.getSelectedObject() != null) {
+            return m_groupTable.getSelectedObject();
+        }
+        else if (m_licenseTable.getSelectedObject() != null) {
+            return m_licenseTable.getSelectedObject();
+        }
+        else if (m_targetTable.getSelectedObject() != null) {
+            return m_targetTable.getSelectedObject();
+        }
+        return null;
+    }
+    
+    /**
+     * Makes sure there is only one selected item at a time.
+     */
+    void deselectOthers(Descriptor descriptor) {
+        m_bundleTable.deselectOthers(descriptor);
+        m_groupTable.deselectOthers(descriptor);
+        m_licenseTable.deselectOthers(descriptor);
+        m_targetTable.deselectOthers(descriptor);
+    }
+    
+    /**
      * Label that can be used a s {@link StatusHandler} for the tables. Will report
      * a successful connection when all components are happy.
      */
     private static class StatusLabel extends Label implements StatusHandler {
         private final Map<String, Boolean> m_statuses = new HashMap<String, Boolean>();
         
+        /**
+         * Indicates whether there should be detailed information about a broken connection.
+         */
+        private static final boolean VERBOSE = true;
+        
         public StatusLabel() {
             setText("checking server status...");
         }
@@ -216,9 +276,11 @@
             else {
                 StringBuilderImpl sb = new StringBuilderImpl();
                 sb.append("Error communicating with server.");
-                for (Map.Entry<String, Boolean> entry : m_statuses.entrySet()) {
-                    if (!entry.getValue()) {
-                        sb.append(" (" + entry.getKey() + ")");
+                if (VERBOSE) {
+                    for (Map.Entry<String, Boolean> entry : m_statuses.entrySet()) {
+                        if (!entry.getValue()) {
+                            sb.append(" (" + entry.getKey() + ")");
+                        }
                     }
                 }
                 setText(sb.toString());
@@ -226,6 +288,4 @@
             }
         }
     }
-    
-    
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/ObjectTable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/ObjectTable.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/ObjectTable.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/ObjectTable.java Wed Jul 15 22:16:11 2009
@@ -19,23 +19,35 @@
 package org.apache.ace.client;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.ace.client.Main.StatusHandler;
+import org.apache.ace.client.services.AssociationService;
+import org.apache.ace.client.services.AssociationServiceAsync;
+import org.apache.ace.client.services.Descriptor;
 
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.DockPanel;
 import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.ToggleButton;
+import com.google.gwt.user.client.ui.FocusPanel;
 
 /**
  * Basic table for using a valueobject per row.
  */
-public abstract class ObjectTable<T> extends FlexTable {
+public abstract class ObjectTable<T extends Descriptor> extends FlexTable {
     private final StatusHandler m_handler;
+    private final Main m_main;
     
-    private final Map<T, ToggleButton> m_widgets = new HashMap<T, ToggleButton>();
+    private final Map<T, ObjectPanel> m_panels = new HashMap<T, ObjectPanel>();
+    
+    private AssociationServiceAsync m_associationService = GWT.create(AssociationService.class);
     
     /**
      * This callback is used for all 'get*' calls.
@@ -49,16 +61,16 @@
             int row = 0;
             // Create a button for every element, and reuse buttons for the ones we already know.
             for (T t : result) {
-                ToggleButton button = m_widgets.get(t);
-                if (button == null) {
-                    button = new ToggleButton();
-                    button.addClickHandler(m_buttonGroup);
-                    m_widgets.put(t, button);
+                ObjectPanel panel = m_panels.get(t);
+                if (panel == null) {
+                    panel = new ObjectPanel(t);
+                    panel.addToGroup(m_buttonGroup);
+                    m_panels.put(t, panel);
                 }
-                button.setText(getText(t));
-                if (getRowCount() <= row || !getWidget(row, 0).equals(button)) {
+                panel.setText(getText(t));
+                if (getRowCount() <= row || !getWidget(row, 0).equals(panel)) {
                     // Setting the widget again might screw up focus
-                    setWidget(row, 0, button);
+                    setWidget(row, 0, panel);
                 }
                 row++;
             }
@@ -70,29 +82,76 @@
     };
     
     /**
-     * Pops up all other buttons in the same group when one gets clicked;
+     * Deselects all other checkboxes in the same group when one gets clicked;
      * this way, we end up with a single selected button.
      */
     private final ClickHandler m_buttonGroup = new ClickHandler() {
         public void onClick(ClickEvent event) {
-            for (ToggleButton w : m_widgets.values()) {
-                if (!w.equals(event.getSource())) {
-                    w.setDown(false);
+            for (ObjectPanel w : m_panels.values()) {
+                if (!w.owns(event.getSource())) {
+                    w.setChecked(false);
                 }
             }
         }
     };
 
-    public ObjectTable(StatusHandler handler) {
+    /**
+     * Sole constructor for this class; all subclasses must delegate to this one.
+     */
+    public ObjectTable(StatusHandler handler, Main main) {
         m_handler = handler;
+        m_main = main;
+    }
+    
+    
+    /**
+     * Interprets the given value object for some column.
+     */
+    protected abstract String getText(T object);
+    
+    /**
+     * Gets a unique ID for this table.
+     * @return
+     */
+    protected abstract String getTableID();
+    
+    /**
+     * Invokes the necessary service call to get the latest
+     * set of value objects from the server, passing the given callback.
+     */
+    protected abstract void getDescriptors(AsyncCallback<T[]> callback);
+
+    /**
+     * Removes the given object from the repository.
+     */
+    protected abstract void remove(T object, AsyncCallback<Void> callback);
+    
+    /**
+     * States whether removal of this object is allowed.
+     */
+    protected boolean canDelete() {
+        return true;
+    }
+    
+
+    /**
+     * Finds the currently checked object, or <code>null</code> if none is found.
+     */
+    public T getCheckedObject() {
+        for (Map.Entry<T, ObjectPanel> entry : m_panels.entrySet()) {
+            if (entry.getValue().isChecked()) {
+                return entry.getKey();
+            }
+        }
+        return null;
     }
     
     /**
      * Finds the currently selected object, or <code>null</code> if none is found.
      */
-    T getSelectedObject() {
-        for (Map.Entry<T, ToggleButton> entry : m_widgets.entrySet()) {
-            if (entry.getValue() instanceof ToggleButton && ((ToggleButton) entry.getValue()).isDown()) {
+    public T getSelectedObject() {
+        for (Map.Entry<T, ObjectPanel> entry : m_panels.entrySet()) {
+            if (entry.getValue().isSelected()) {
                 return entry.getKey();
             }
         }
@@ -102,24 +161,149 @@
     /**
      * Updates the contents of this table
      */
-    void updateTable() {
-        callService(m_asyncCallback);
+    public void updateTable() {
+        getDescriptors(m_asyncCallback);
     }
     
     /**
-     * Interprets the given value object for some column.
+     * Highlights the given objects, if they are in this table.
      */
-    protected abstract String getText(T object);
+    public void highlight(List<Descriptor> descriptors) {
+        for (Map.Entry<T, ObjectPanel> entry : m_panels.entrySet()) {
+            if (descriptors.contains(entry.getKey())) {
+                entry.getValue().addStyleDependentName("related");
+            }
+            else {
+                entry.getValue().removeStyleDependentName("related");
+            }
+        }
+    }
     
     /**
-     * Gets a unique ID for this table.
-     * @return
+     * Deselects all objects, except for the one given.
      */
-    protected abstract String getTableID();
-    
+    public void deselectOthers(Descriptor descriptor) {
+        for (Map.Entry<T, ObjectPanel> entry : m_panels.entrySet()) {
+            if (!entry.getKey().equals(descriptor)) {
+                entry.getValue().setSelected(false);
+            }
+        }
+    }
+
     /**
-     * Invokes the necessary service call to get the latest
-     * set of value objects from the server, passing the given callback.
+     * {@link ObjectPanel} represents exactly one Descriptor. It will handle selection, and can
+     * unlink and delete the related object.
      */
-    protected abstract void callService(AsyncCallback<T[]> callback);
+    private class ObjectPanel extends FocusPanel {
+        private final CheckBox m_checkbox;
+        private boolean m_selected;
+
+        public ObjectPanel(final T object) {
+            DockPanel mainPanel = new DockPanel();
+
+            m_checkbox = new CheckBox(getText(object));
+            m_checkbox.setStylePrimaryName("objectpaneltext");
+            mainPanel.add(m_checkbox, DockPanel.WEST);
+
+            if (canDelete()) {
+                Button delete = new Button("x");
+                delete.setTitle("Delete this object");
+                mainPanel.add(delete, DockPanel.EAST);
+                delete.addClickHandler(new ClickHandler() {
+                    public void onClick(ClickEvent event) {
+                        ObjectTable.this.remove(object, new AsyncCallback<Void>() {
+                            public void onFailure(Throwable caught) {
+                                Window.alert("Error deleting object");
+                            }
+                            public void onSuccess(Void result) {
+                                m_main.updateUI();
+                            }
+                        });
+                    }
+                });
+            }
+            
+            Button unlink = new Button("-");
+            unlink.setTitle("Unlink this object from the current selection");
+            mainPanel.add(unlink, DockPanel.EAST);
+            unlink.addClickHandler(new ClickHandler() {
+                public void onClick(ClickEvent event) {
+                    m_associationService.unlink(object, m_main.getSelectedObject(), new AsyncCallback<Void>() {
+                        public void onFailure(Throwable caught) {
+                            Window.alert("Error breaking link");
+                        }
+                        public void onSuccess(Void result) {
+                            m_main.updateHighlight();
+                        }
+                        
+                    });
+                    event.stopPropagation(); // we don't want the panel to get the click
+                }
+            });
+            
+            add(mainPanel);
+            
+            setStylePrimaryName("objectpanel");
+            
+            addClickHandler(new ClickHandler() {
+                public void onClick(ClickEvent event) {
+                    setSelected(true);
+                    m_main.deselectOthers(object);
+                    m_main.updateHighlight();
+                }
+            });
+        }
+        
+        public boolean isChecked() {
+            return m_checkbox.getValue();
+        }
+        
+        public void setChecked(boolean b) {
+            m_checkbox.setValue(b);
+        }
+        
+        public boolean isSelected() {
+            return m_selected;
+        }
+        
+        public void setSelected(boolean selected) {
+            m_selected = selected;
+            if (selected) {
+                addStyleDependentName("selected");
+                m_checkbox.addStyleDependentName("selected");
+            }
+            else {
+                removeStyleDependentName("selected");
+                m_checkbox.removeStyleDependentName("selected");
+            }
+        }
+        
+        public void setRelated(boolean related) {
+            if (related) {
+                addStyleDependentName("related");
+            }
+            else {
+                removeStyleDependentName("related");
+            }
+        }
+
+        public void setText(String text) {
+            m_checkbox.setText(text);
+        }
+        
+        /**
+         * Returns whether the given object is 'owned' by this panel.
+         */
+        public boolean owns(Object object) {
+            return object.equals(m_checkbox);
+        }
+        
+        /**
+         * Registers a clickhandler with the checkbox; this is used to make sure that at most one
+         * checkbox in a column is checked.
+         */
+        public void addToGroup(ClickHandler handler) {
+            m_checkbox.addClickHandler(handler);
+        }
+    }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/TargetTable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/TargetTable.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/TargetTable.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/TargetTable.java Wed Jul 15 22:16:11 2009
@@ -32,12 +32,12 @@
 public class TargetTable extends ObjectTable<TargetDescriptor> {
     private TargetServiceAsync m_targetService = GWT.create(TargetService.class);
 
-    TargetTable(StatusHandler handler) {
-        super(handler);
+    TargetTable(StatusHandler handler, Main main) {
+        super(handler, main);
     }
 
     @Override
-    protected void callService(AsyncCallback<TargetDescriptor[]> callback) {
+    protected void getDescriptors(AsyncCallback<TargetDescriptor[]> callback) {
         m_targetService.getTargets(callback);
     }
 
@@ -50,4 +50,14 @@
     protected String getTableID() {
         return "targets";
     }
+
+    @Override
+    protected void remove(TargetDescriptor object, AsyncCallback<Void> callback) {
+        throw new UnsupportedOperationException();
+    }
+    
+    @Override
+    protected boolean canDelete() {
+        return false;
+    }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationService.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationService.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationService.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationService.java Wed Jul 15 22:16:11 2009
@@ -42,4 +42,14 @@
      * and the 'auto approve' will be turned on.
      */
     void link(LicenseDescriptor license, TargetDescriptor target) throws Exception;
+
+    /**
+     * Unlinks the two given descriptors.
+     */
+    void unlink(Descriptor one, Descriptor other) throws Exception;
+
+    /**
+     * Gets all the descriptors that are in some way related to the given one.
+     */
+    Descriptor[] getRelated(Descriptor o) throws Exception;
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationServiceAsync.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationServiceAsync.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationServiceAsync.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/AssociationServiceAsync.java Wed Jul 15 22:16:11 2009
@@ -27,4 +27,6 @@
     void link(BundleDescriptor bundle, GroupDescriptor group, AsyncCallback<Void> callback);
     void link(GroupDescriptor group, LicenseDescriptor license, AsyncCallback<Void> callback);
     void link(LicenseDescriptor license, TargetDescriptor target, AsyncCallback<Void> callback);
+    void unlink(Descriptor license, Descriptor target, AsyncCallback<Void> callback);
+    void getRelated(Descriptor o, AsyncCallback<Descriptor[]> callback);
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleDescriptor.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleDescriptor.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleDescriptor.java Wed Jul 15 22:16:11 2009
@@ -23,34 +23,15 @@
 /**
  * Value object for communicating bundle status between the server and the client.
  */
-public class BundleDescriptor implements Serializable {
+public class BundleDescriptor extends Descriptor implements Serializable {
     /**
      * Generated serialVersionUID
      */
     private static final long serialVersionUID = 6017517453464153123L;
     
-    private String m_name;
-    
     public BundleDescriptor() {}
 
     public BundleDescriptor(String name) {
-        m_name = name;
-    }
-
-    public String getName() {
-        return m_name;
-    }
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (obj.getClass().equals(getClass())) {
-            return m_name.equals(((BundleDescriptor) obj).m_name);
-        }
-        return false;
-    }
-    
-    @Override
-    public int hashCode() {
-        return m_name.hashCode();
+        super(name);
     }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleService.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleService.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleService.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleService.java Wed Jul 15 22:16:11 2009
@@ -30,4 +30,9 @@
      * Gets Bundle descriptors for all available Bundles.
      */
     BundleDescriptor[] getBundles() throws Exception;
+    
+    /**
+     * Removes the given descriptor from the repository.
+     */
+    void remove(BundleDescriptor descriptor) throws Exception;
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleServiceAsync.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleServiceAsync.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleServiceAsync.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/BundleServiceAsync.java Wed Jul 15 22:16:11 2009
@@ -25,4 +25,5 @@
  */
 public interface BundleServiceAsync {
     void getBundles(AsyncCallback<BundleDescriptor[]> callback);
+    void remove(BundleDescriptor descriptor, AsyncCallback<Void> callback);
 }

Added: incubator/ace/trunk/webui/src/org/apache/ace/client/services/Descriptor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/Descriptor.java?rev=794436&view=auto
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/Descriptor.java (added)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/Descriptor.java Wed Jul 15 22:16:11 2009
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.services;
+
+import java.io.Serializable;
+
+/**
+ * Base class for all descriptors
+ */
+public class Descriptor implements Serializable {
+    /**
+     * Generated serialVersionUID
+     */
+    private static final long serialVersionUID = 4101795241648964869L;
+    
+    private String m_name;
+
+    public Descriptor() {}
+    
+    public Descriptor(String name) {
+        m_name = name;
+    }
+
+    public String getName() {
+        return m_name;
+    }
+    
+
+    /**
+     * Remember to override this method in subclasses that rely on more than just the name.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Descriptor) {
+            return getName().equals(((Descriptor) obj).getName());
+        }
+        return false;
+    }
+    
+    /**
+     * Remember to override this method in subclasses that rely on more than just the name.
+     */
+    @Override
+    public int hashCode() {
+        return getName().hashCode();
+    }
+}
\ No newline at end of file

Propchange: incubator/ace/trunk/webui/src/org/apache/ace/client/services/Descriptor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupDescriptor.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupDescriptor.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupDescriptor.java Wed Jul 15 22:16:11 2009
@@ -23,35 +23,15 @@
 /**
  * Value object for communicating group status between the server and the client.
  */
-public class GroupDescriptor implements Serializable {
+public class GroupDescriptor extends Descriptor implements Serializable {
     /**
      * Generated serialVersionUID
      */
     private static final long serialVersionUID = 6703134869983034189L;
 
-    private String m_name;
-    
     public GroupDescriptor() {}
 
     public GroupDescriptor(String name) {
-        m_name = name;
+        super(name);
     }
-
-    public String getName() {
-        return m_name;
-    }
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (obj.getClass().equals(getClass())) {
-            return m_name.equals(((GroupDescriptor) obj).m_name);
-        }
-        return false;
-    }
-    
-    @Override
-    public int hashCode() {
-        return m_name.hashCode();
-    }
-
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupService.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupService.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupService.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupService.java Wed Jul 15 22:16:11 2009
@@ -35,4 +35,9 @@
      * Adds a new group with the given name.
      */
     void addGroup(String name) throws Exception;
+    
+    /**
+     * Removes the given descriptor from the repository.
+     */
+    void remove(GroupDescriptor descriptor) throws Exception;
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupServiceAsync.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupServiceAsync.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupServiceAsync.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/GroupServiceAsync.java Wed Jul 15 22:16:11 2009
@@ -26,4 +26,5 @@
 public interface GroupServiceAsync {
     void getGroups(AsyncCallback<GroupDescriptor[]> callback);
     void addGroup(String name, AsyncCallback<Void> callback);
+    void remove(GroupDescriptor descriptor, AsyncCallback<Void> callback);
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseDescriptor.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseDescriptor.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseDescriptor.java Wed Jul 15 22:16:11 2009
@@ -23,34 +23,15 @@
 /**
  * Value object for communicating license status between the server and the client.
  */
-public class LicenseDescriptor implements Serializable {
+public class LicenseDescriptor extends Descriptor implements Serializable {
     /**
      * Generated serialVersionUID
      */
     private static final long serialVersionUID = 5386417593195995864L;
 
-    private String m_name;
-    
     public LicenseDescriptor() {}
 
     public LicenseDescriptor(String name) {
-        m_name = name;
-    }
-
-    public String getName() {
-        return m_name;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj.getClass().equals(getClass())) {
-            return m_name.equals(((LicenseDescriptor) obj).m_name);
-        }
-        return false;
-    }
-    
-    @Override
-    public int hashCode() {
-        return m_name.hashCode();
+        super(name);
     }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseService.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseService.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseService.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseService.java Wed Jul 15 22:16:11 2009
@@ -35,4 +35,9 @@
      * Adds a new license with the given name.
      */
     void addLicense(String name) throws Exception;
+    
+    /**
+     * Removes the given descriptor from the repository.
+     */
+    void remove(LicenseDescriptor descriptor) throws Exception;
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseServiceAsync.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseServiceAsync.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseServiceAsync.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/LicenseServiceAsync.java Wed Jul 15 22:16:11 2009
@@ -26,4 +26,5 @@
 public interface LicenseServiceAsync {
     void getLicenses(AsyncCallback<LicenseDescriptor[]> callback);
     void addLicense(String name, AsyncCallback<Void> callback);
+    void remove(LicenseDescriptor descriptor, AsyncCallback<Void> callback);
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/client/services/TargetDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/client/services/TargetDescriptor.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/client/services/TargetDescriptor.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/client/services/TargetDescriptor.java Wed Jul 15 22:16:11 2009
@@ -22,8 +22,10 @@
 
 /**
  * Value object for communicating target status between the server and the client.
+ * 
+ * Note that we do not override hashcode and equals, since we only need the name for identity.
  */
-public class TargetDescriptor implements Serializable {
+public class TargetDescriptor extends Descriptor implements Serializable {
     /**
      * Generated serialVersionUID
      */
@@ -39,35 +41,16 @@
         OK
     }
     
-    private String m_name;
     private ProvisioningState m_provisioningState;
     
     public TargetDescriptor() {}
 
     public TargetDescriptor(String name, ProvisioningState provisioningState) {
-        m_name = name;
+        super(name);
         m_provisioningState = provisioningState;
     }
 
-    public String getName() {
-        return m_name;
-    }
-
     public ProvisioningState getProvisioningState() {
         return m_provisioningState;
     }
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (obj.getClass().equals(getClass())) {
-            return m_name.equals(((TargetDescriptor) obj).m_name);
-        }
-        return false;
-    }
-    
-    @Override
-    public int hashCode() {
-        return m_name.hashCode();
-    }
-
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/server/AssociationServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/AssociationServiceImpl.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/AssociationServiceImpl.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/AssociationServiceImpl.java Wed Jul 15 22:16:11 2009
@@ -18,21 +18,22 @@
  */
 package org.apache.ace.server;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.ace.client.repository.RepositoryAdmin;
+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.repository.Artifact2GroupAssociationRepository;
-import org.apache.ace.client.repository.repository.ArtifactRepository;
 import org.apache.ace.client.repository.repository.Group2LicenseAssociationRepository;
-import org.apache.ace.client.repository.repository.GroupRepository;
 import org.apache.ace.client.repository.repository.License2GatewayAssociationRepository;
-import org.apache.ace.client.repository.repository.LicenseRepository;
 import org.apache.ace.client.repository.stateful.StatefulGatewayObject;
-import org.apache.ace.client.repository.stateful.StatefulGatewayRepository;
 import org.apache.ace.client.services.AssociationService;
 import org.apache.ace.client.services.BundleDescriptor;
+import org.apache.ace.client.services.Descriptor;
 import org.apache.ace.client.services.GroupDescriptor;
 import org.apache.ace.client.services.LicenseDescriptor;
 import org.apache.ace.client.services.TargetDescriptor;
@@ -51,34 +52,46 @@
 
     public void link(BundleDescriptor bundle, GroupDescriptor group) throws Exception {
         Artifact2GroupAssociationRepository a2gr = Activator.getService(getThreadLocalRequest(), Artifact2GroupAssociationRepository.class);
-        ArtifactRepository ar = Activator.getService(getThreadLocalRequest(), ArtifactRepository.class);
-        GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
         
-        ArtifactObject a = ar.get(Activator.getContext().createFilter("(" + ArtifactObject.KEY_ARTIFACT_NAME + "=" + bundle.getName() + ")")).get(0);
-        GroupObject g = gr.get(Activator.getContext().createFilter("(" + GroupObject.KEY_NAME + "=" + group.getName() + ")")).get(0);
+        ArtifactObject a = (ArtifactObject) ObjectMapping.unwrap(bundle);
+        GroupObject g = (GroupObject) ObjectMapping.unwrap(group);
         
         a2gr.create(a, g);
     }
 
+    private void unlink(BundleDescriptor bundle, GroupDescriptor group) throws Exception {
+        Artifact2GroupAssociationRepository a2gr = Activator.getService(getThreadLocalRequest(), Artifact2GroupAssociationRepository.class);
+        
+        ArtifactObject a = (ArtifactObject) ObjectMapping.unwrap(bundle);
+        GroupObject g = (GroupObject) ObjectMapping.unwrap(group);
+        
+        a2gr.remove(a.getAssociationsWith(g).get(0));
+    }
+
     public void link(GroupDescriptor group, LicenseDescriptor license) throws Exception {
         Group2LicenseAssociationRepository g2lr = Activator.getService(getThreadLocalRequest(), Group2LicenseAssociationRepository.class);
-        GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
-        LicenseRepository lr = Activator.getService(getThreadLocalRequest(), LicenseRepository.class);
-        
-        GroupObject g = gr.get(Activator.getContext().createFilter("(" + GroupObject.KEY_NAME + "=" + group.getName() + ")")).get(0);
-        LicenseObject l = lr.get(Activator.getContext().createFilter("(" + LicenseObject.KEY_NAME + "=" + license.getName() + ")")).get(0);
 
+        GroupObject g = (GroupObject) ObjectMapping.unwrap(group);
+        LicenseObject l = (LicenseObject) ObjectMapping.unwrap(license);
+        
         g2lr.create(g, l);
     }
 
+    private void unlink(GroupDescriptor group, LicenseDescriptor license) throws Exception {
+        Group2LicenseAssociationRepository g2lr = Activator.getService(getThreadLocalRequest(), Group2LicenseAssociationRepository.class);
+
+        GroupObject g = (GroupObject) ObjectMapping.unwrap(group);
+        LicenseObject l = (LicenseObject) ObjectMapping.unwrap(license);
+        
+        g2lr.remove(g.getAssociationsWith(l).get(0));
+    }
+
     public void link(LicenseDescriptor license, TargetDescriptor target) throws Exception {
         License2GatewayAssociationRepository l2tr = Activator.getService(getThreadLocalRequest(), License2GatewayAssociationRepository.class);
-        LicenseRepository lr = Activator.getService(getThreadLocalRequest(), LicenseRepository.class);
-        StatefulGatewayRepository gr = Activator.getService(getThreadLocalRequest(), StatefulGatewayRepository.class);
-        
-        LicenseObject l = lr.get(Activator.getContext().createFilter("(" + LicenseObject.KEY_NAME + "=" + license.getName() + ")")).get(0);
-        StatefulGatewayObject g = gr.get(Activator.getContext().createFilter("(" + GatewayObject.KEY_ID + "=" + target.getName() + ")")).get(0);
 
+        LicenseObject l = (LicenseObject) ObjectMapping.unwrap(license);
+        StatefulGatewayObject g = (StatefulGatewayObject) ObjectMapping.unwrap(target);
+        
         if (!g.isRegistered()) {
             g.register();
             g.setAutoApprove(true);
@@ -86,4 +99,98 @@
         
         l2tr.create(l, g.getGatewayObject());
     }
+
+    private void unlink(LicenseDescriptor license, TargetDescriptor target) throws Exception {
+        License2GatewayAssociationRepository l2tr = Activator.getService(getThreadLocalRequest(), License2GatewayAssociationRepository.class);
+
+        LicenseObject l = (LicenseObject) ObjectMapping.unwrap(license);
+        StatefulGatewayObject g = (StatefulGatewayObject) ObjectMapping.unwrap(target);
+        
+        l2tr.remove(l.getAssociationsWith(g.getGatewayObject()).get(0));
+    }
+    
+    public void unlink(Descriptor one, Descriptor other) throws Exception {
+        _unlink(one, other);
+        _unlink(other, one);
+    }
+    
+    /**
+     * Helper method for the unlink method, which allows easier checking of 'both ways' of an association.
+     */
+    private void _unlink(Descriptor one, Descriptor other) throws Exception {
+        if (one instanceof BundleDescriptor && other instanceof GroupDescriptor) {
+            unlink((BundleDescriptor) one, (GroupDescriptor) other);
+        }
+        else if (one instanceof GroupDescriptor && other instanceof LicenseDescriptor) {
+            unlink((GroupDescriptor) one, (LicenseDescriptor) other);
+        }
+        else if (one instanceof LicenseDescriptor && other instanceof TargetDescriptor) {
+            unlink((LicenseDescriptor) one, (TargetDescriptor) other);
+        }
+    }
+
+    public Descriptor[] getRelated(Descriptor o) throws Exception {
+        RepositoryObject a = ObjectMapping.unwrap(o);
+        List<RepositoryObject> relatedObjects = getRelated(a);
+        List<Descriptor> descriptors = ObjectMapping.wrap(relatedObjects);
+        return descriptors.toArray(new Descriptor[descriptors.size()]);
+    }
+    
+    /**
+     * Helper method that finds all related {@link RepositoryObject}s for a given one.
+     */
+    private List<RepositoryObject> getRelated(RepositoryObject object) throws Exception {
+        List<RepositoryObject> result = new ArrayList<RepositoryObject>();
+        if (object instanceof ArtifactObject) {
+            List<GroupObject> groups = getRelated(object, GroupObject.class);
+            List<LicenseObject> licenses = getRelated(groups, LicenseObject.class);
+            List<GatewayObject> targets = getRelated(licenses, GatewayObject.class);
+            result.addAll(groups);
+            result.addAll(licenses);
+            result.addAll(TargetServiceImpl.instance().findSGOs(targets));
+        }
+        else if (object instanceof GroupObject) {
+            List<ArtifactObject> artifacts = getRelated(object, ArtifactObject.class);
+            List<LicenseObject> licenses = getRelated(object, LicenseObject.class);
+            List<GatewayObject> targets = getRelated(licenses, GatewayObject.class);
+            result.addAll(artifacts);
+            result.addAll(licenses);
+            result.addAll(TargetServiceImpl.instance().findSGOs(targets));
+        }
+        else if (object instanceof LicenseObject) {
+            List<GroupObject> groups = getRelated(object, GroupObject.class);
+            List<ArtifactObject> artifacts = getRelated(groups, ArtifactObject.class);
+            List<GatewayObject> targets = getRelated(object, GatewayObject.class);
+            result.addAll(artifacts);
+            result.addAll(groups);
+            result.addAll(TargetServiceImpl.instance().findSGOs(targets));
+        }
+        else if (object instanceof StatefulGatewayObject) {
+            List<LicenseObject> licenses = getRelated(object, LicenseObject.class);
+            List<GroupObject> groups = getRelated(licenses, GroupObject.class);
+            List<ArtifactObject> artifacts = getRelated(groups, ArtifactObject.class);
+            result.addAll(artifacts);
+            result.addAll(groups);
+            result.addAll(licenses);
+        }
+        return result;
+    }
+    
+    /**
+     * 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) {
+        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;
+    }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/server/BundleServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/BundleServiceImpl.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/BundleServiceImpl.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/BundleServiceImpl.java Wed Jul 15 22:16:11 2009
@@ -18,35 +18,66 @@
  */
 package org.apache.ace.server;
 
-import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.ace.client.repository.RepositoryObject;
 import org.apache.ace.client.repository.helper.bundle.BundleHelper;
 import org.apache.ace.client.repository.object.ArtifactObject;
 import org.apache.ace.client.repository.repository.ArtifactRepository;
 import org.apache.ace.client.services.BundleDescriptor;
 import org.apache.ace.client.services.BundleService;
-
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+import org.apache.ace.client.services.Descriptor;
 
 /**
- * Returns all bundles the repository; other types of artifacts are ignored.
+ * This service only checks for bundles; all other artifacts are ignored.
  */
-public class BundleServiceImpl extends RemoteServiceServlet implements BundleService {
+public class BundleServiceImpl extends ObjectServiceImpl<ArtifactObject, BundleDescriptor> implements BundleService {
     /**
      * Generated serialVersionUID
      */
     private static final long serialVersionUID = -355941324100124904L;
+    
+    private static BundleServiceImpl m_instance;
+    
+    public BundleServiceImpl() {
+        m_instance = this;
+    }
+    
+    static BundleServiceImpl instance() {
+        return m_instance;
+    }
 
     public BundleDescriptor[] getBundles() throws Exception {
+        List<BundleDescriptor> descriptors = getDescriptors();
+        return getDescriptors().toArray(new BundleDescriptor[descriptors.size()]);
+    }
+    
+    public List<ArtifactObject> get() throws Exception {
+        ArtifactRepository ar = Activator.getService(getThreadLocalRequest(), ArtifactRepository.class);
+        return ar.get(Activator.getContext().createFilter("(" + ArtifactObject.KEY_MIMETYPE + "=" + BundleHelper.MIMETYPE + ")"));
+    }
+    
+    @Override
+    public void remove(ArtifactObject object) throws Exception {
+        ArtifactRepository ar = Activator.getService(getThreadLocalRequest(), ArtifactRepository.class);
+        ar.remove(object);
+    }
+    
+    @Override
+    public BundleDescriptor wrap(RepositoryObject object) {
+        if (object instanceof ArtifactObject) {
+            return new BundleDescriptor(((ArtifactObject) object).getName());
+        }
+        throw new IllegalArgumentException();
+    }
+    
+    @Override
+    public ArtifactObject unwrap(Descriptor descriptor) throws Exception {
         ArtifactRepository ar = Activator.getService(getThreadLocalRequest(), ArtifactRepository.class);
-        
-        List<BundleDescriptor> result = new ArrayList<BundleDescriptor>();
-        
-        for (ArtifactObject a : ar.get(Activator.getContext().createFilter("(" + ArtifactObject.KEY_MIMETYPE + "=" + BundleHelper.MIMETYPE + ")"))) {
-            result.add(new BundleDescriptor(a.getName()));
+        List<ArtifactObject> list = ar.get(Activator.getContext().createFilter("(" + ArtifactObject.KEY_ARTIFACT_NAME + "=" + descriptor.getName() + ")"));
+        if (list.size() == 1) {
+            return list.get(0);
         }
-        
-        return result.toArray(new BundleDescriptor[result.size()]);
+        throw new IllegalArgumentException();
     }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/server/GroupServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/GroupServiceImpl.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/GroupServiceImpl.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/GroupServiceImpl.java Wed Jul 15 22:16:11 2009
@@ -18,36 +18,44 @@
  */
 package org.apache.ace.server;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.ace.client.repository.RepositoryObject;
 import org.apache.ace.client.repository.object.GroupObject;
 import org.apache.ace.client.repository.repository.GroupRepository;
+import org.apache.ace.client.services.Descriptor;
 import org.apache.ace.client.services.GroupDescriptor;
 import org.apache.ace.client.services.GroupService;
 
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
-
-public class GroupServiceImpl extends RemoteServiceServlet implements GroupService {
+public class GroupServiceImpl extends ObjectServiceImpl<GroupObject, GroupDescriptor> implements GroupService {
     /**
      * Generated serialVersionUID
      */
-    private static final long serialVersionUID = -5744202709461660202L;
+    private static final long serialVersionUID = 4353842101585350694L;
 
+    private static GroupServiceImpl m_instance;
+    
+    public GroupServiceImpl() {
+        m_instance = this;
+    }
+    
+    static GroupServiceImpl instance() {
+        return m_instance;
+    }
+    
     public GroupDescriptor[] getGroups() throws Exception {
-        GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
-        
-        List<GroupDescriptor> result = new ArrayList<GroupDescriptor>();
-        
-        for (GroupObject g : gr.get()) {
-            result.add(new GroupDescriptor(g.getName()));
-        }
-        
-        return result.toArray(new GroupDescriptor[result.size()]);
+        List<GroupDescriptor> descriptors = getDescriptors();
+        return getDescriptors().toArray(new GroupDescriptor[descriptors.size()]);
     }
 
+    @Override
+    public List<GroupObject> get() throws Exception {
+        GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
+        return gr.get();
+    }
+    
     public void addGroup(String name) throws Exception {
         GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
         
@@ -55,4 +63,28 @@
         props.put(GroupObject.KEY_NAME, name);
         gr.create(props, null);
     }
+
+    @Override
+    public void remove(GroupObject object) throws Exception {
+        GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
+        gr.remove(object);
+    }
+
+    @Override
+    public GroupDescriptor wrap(RepositoryObject object) {
+        if (object instanceof GroupObject) {
+            return new GroupDescriptor(((GroupObject) object).getName());
+        }
+        throw new IllegalArgumentException();
+    }
+    
+    @Override
+    public GroupObject unwrap(Descriptor descriptor) throws Exception {
+        GroupRepository gr = Activator.getService(getThreadLocalRequest(), GroupRepository.class);
+        List<GroupObject> list = gr.get(Activator.getContext().createFilter("(" + GroupObject.KEY_NAME + "=" + descriptor.getName() + ")"));
+        if (list.size() == 1) {
+            return list.get(0);
+        }
+        throw new IllegalArgumentException();
+    }
 }

Modified: incubator/ace/trunk/webui/src/org/apache/ace/server/LicenseServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/LicenseServiceImpl.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/LicenseServiceImpl.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/LicenseServiceImpl.java Wed Jul 15 22:16:11 2009
@@ -18,36 +18,43 @@
  */
 package org.apache.ace.server;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.ace.client.repository.RepositoryObject;
 import org.apache.ace.client.repository.object.LicenseObject;
 import org.apache.ace.client.repository.repository.LicenseRepository;
+import org.apache.ace.client.services.Descriptor;
 import org.apache.ace.client.services.LicenseDescriptor;
 import org.apache.ace.client.services.LicenseService;
 
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
-
-public class LicenseServiceImpl extends RemoteServiceServlet implements LicenseService {
+public class LicenseServiceImpl extends ObjectServiceImpl<LicenseObject, LicenseDescriptor> implements LicenseService {
     /**
      * Generated serialVersionUID
      */
     private static final long serialVersionUID = -8435568874637903362L;
 
+    private static LicenseServiceImpl m_instance;
+    
+    public LicenseServiceImpl() {
+        m_instance = this;
+    }
+    
+    static LicenseServiceImpl instance() {
+        return m_instance;
+    }
+    
     public LicenseDescriptor[] getLicenses() throws Exception {
-        LicenseRepository lr = Activator.getService(getThreadLocalRequest(), LicenseRepository.class);
-        
-        List<LicenseDescriptor> result = new ArrayList<LicenseDescriptor>();
-        
-        for (LicenseObject l : lr.get()) {
-            result.add(new LicenseDescriptor(l.getName()));
-        }
-        
-        return result.toArray(new LicenseDescriptor[result.size()]);
+        List<LicenseDescriptor> descriptors = getDescriptors();
+        return getDescriptors().toArray(new LicenseDescriptor[descriptors.size()]);
     }
-
+    
+    @Override
+    public List<LicenseObject> get() throws Exception {
+        return Activator.getService(getThreadLocalRequest(), LicenseRepository.class).get();
+    }
+    
     public void addLicense(String name) throws Exception {
         LicenseRepository gr = Activator.getService(getThreadLocalRequest(), LicenseRepository.class);
         
@@ -55,4 +62,28 @@
         props.put(LicenseObject.KEY_NAME, name);
         gr.create(props, null);
     }
+    
+    @Override
+    public void remove(LicenseObject object) throws Exception {
+        LicenseRepository lr = Activator.getService(getThreadLocalRequest(), LicenseRepository.class);
+        lr.remove(object);
+    }
+    
+    @Override
+    public LicenseDescriptor wrap(RepositoryObject object) {
+        if (object instanceof LicenseObject) {
+            return new LicenseDescriptor(((LicenseObject) object).getName());
+        }
+        throw new IllegalArgumentException();
+    }
+
+    @Override
+    public LicenseObject unwrap(Descriptor descriptor) throws Exception {
+        LicenseRepository lr = Activator.getService(getThreadLocalRequest(), LicenseRepository.class);
+        List<LicenseObject> list = lr.get(Activator.getContext().createFilter("(" + LicenseObject.KEY_NAME + "=" + descriptor.getName() + ")"));
+        if (list.size() == 1) {
+            return list.get(0);
+        }
+        throw new IllegalArgumentException();
+    }
 }

Added: incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectMapping.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectMapping.java?rev=794436&view=auto
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectMapping.java (added)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectMapping.java Wed Jul 15 22:16:11 2009
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.ArtifactObject;
+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 org.apache.ace.client.services.BundleDescriptor;
+import org.apache.ace.client.services.Descriptor;
+import org.apache.ace.client.services.GroupDescriptor;
+import org.apache.ace.client.services.LicenseDescriptor;
+import org.apache.ace.client.services.TargetDescriptor;
+
+/**
+ * This class contains helper methods that ease the mapping from {@link RepositoryObject}s to {@link Descriptor}s.
+ */
+public class ObjectMapping {
+    /**
+     * Wraps {@link RepositoryObject}s in {@link Descriptor}s.
+     */
+    public static List<Descriptor> wrap(List<RepositoryObject> objects) {
+        List<Descriptor> result = new ArrayList<Descriptor>();
+        for (RepositoryObject o : objects) {
+            result.add(wrap(o));
+        }
+        return result;
+    }
+    
+    /**
+     * Wraps a single {@link RepositoryObject} in a {@link Descriptor}.
+     */
+    public static Descriptor wrap(RepositoryObject object) {
+        return findService(object).wrap(object);
+    }
+
+    /**
+     * Unwraps a single {@link Descriptor}.
+     */
+    public static RepositoryObject unwrap(Descriptor descriptor) throws Exception {
+        return findService(descriptor).unwrap(descriptor);
+    }
+    
+    /**
+     * Finds the service impl for the given object.
+     */
+    private static ObjectServiceImpl<? extends RepositoryObject, ? extends Descriptor> findService(RepositoryObject object) {
+        if (object instanceof ArtifactObject) {
+            return BundleServiceImpl.instance();
+        }
+        else if (object instanceof GroupObject) {
+            return GroupServiceImpl.instance();
+        }
+        else if (object instanceof LicenseObject) {
+            return LicenseServiceImpl.instance();
+        }
+        else if (object instanceof StatefulGatewayObject) {
+            return TargetServiceImpl.instance();
+        }
+        return null;
+    }
+    
+    /**
+     * Finds the service impl for the given object.
+     */
+    public static ObjectServiceImpl<? extends RepositoryObject, ? extends Descriptor> findService(Descriptor descriptor) {
+        if (descriptor instanceof BundleDescriptor) {
+            return BundleServiceImpl.instance();
+        }
+        else if (descriptor instanceof GroupDescriptor) {
+            return GroupServiceImpl.instance();
+        }
+        else if (descriptor instanceof LicenseDescriptor) {
+            return LicenseServiceImpl.instance();
+        }
+        else if (descriptor instanceof TargetDescriptor) {
+            return TargetServiceImpl.instance();
+        }
+        return null;
+    }
+}

Propchange: incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectMapping.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectServiceImpl.java?rev=794436&view=auto
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectServiceImpl.java (added)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectServiceImpl.java Wed Jul 15 22:16:11 2009
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.services.Descriptor;
+
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+
+/**
+ * Base class for all Service impls. We expect each implementer to have
+ * a static 'instance' method.
+ */
+public abstract class ObjectServiceImpl<REPOOBJECT extends RepositoryObject, DESCRIPTOR extends Descriptor> extends RemoteServiceServlet {
+    private static final long serialVersionUID = 642638564864566760L;
+
+    /**
+     * Unwraps the given descriptor, giving back the original repository object.
+     */
+    public abstract REPOOBJECT unwrap(Descriptor descriptor) throws Exception;
+    
+    /**
+     * Wraps the given object, returning a descriptor.
+     */
+    public abstract DESCRIPTOR wrap(RepositoryObject object);
+    
+    public abstract List<REPOOBJECT> get() throws Exception;
+    
+    public abstract void remove(REPOOBJECT object) throws Exception;
+    
+    public List<DESCRIPTOR> getDescriptors() throws Exception {
+        List<DESCRIPTOR> result = new ArrayList<DESCRIPTOR>();
+        for (REPOOBJECT o : get()) {
+            result.add(wrap(o));
+        }
+        return result;
+    }
+    
+    public void remove(DESCRIPTOR descriptor) throws Exception {
+        remove(unwrap(descriptor));
+    }
+    
+}

Propchange: incubator/ace/trunk/webui/src/org/apache/ace/server/ObjectServiceImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/ace/trunk/webui/src/org/apache/ace/server/TargetServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/src/org/apache/ace/server/TargetServiceImpl.java?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/src/org/apache/ace/server/TargetServiceImpl.java (original)
+++ incubator/ace/trunk/webui/src/org/apache/ace/server/TargetServiceImpl.java Wed Jul 15 22:16:11 2009
@@ -21,19 +21,30 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.object.GatewayObject;
 import org.apache.ace.client.repository.stateful.StatefulGatewayObject;
 import org.apache.ace.client.repository.stateful.StatefulGatewayRepository;
+import org.apache.ace.client.services.Descriptor;
 import org.apache.ace.client.services.TargetDescriptor;
 import org.apache.ace.client.services.TargetService;
 
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
-
-public class TargetServiceImpl extends RemoteServiceServlet implements TargetService {
+public class TargetServiceImpl extends ObjectServiceImpl<StatefulGatewayObject, TargetDescriptor> implements TargetService {
     /**
      * Generated serialVersionUID
      */
     private static final long serialVersionUID = 4501422339245927089L;
 
+    private static TargetServiceImpl m_instance;
+    
+    public TargetServiceImpl() {
+        m_instance = this;
+    }
+    
+    static TargetServiceImpl instance() {
+        return m_instance;
+    }
+    
     /**
      * Helper method to translate between server- and client lingo
      */
@@ -50,15 +61,57 @@
     }
 
     public TargetDescriptor[] getTargets() throws Exception {
+        List<TargetDescriptor> descriptors = getDescriptors();
+        return getDescriptors().toArray(new TargetDescriptor[descriptors.size()]);
+    }
+
+    @Override
+    public List<StatefulGatewayObject> get() throws Exception {
         StatefulGatewayRepository sgr = Activator.getService(getThreadLocalRequest(), StatefulGatewayRepository.class);
         sgr.refresh();
-        
-        List<TargetDescriptor> result = new ArrayList<TargetDescriptor>();
-        
-        for (StatefulGatewayObject sgo : sgr.get()) {
-            result.add(new TargetDescriptor(sgo.getID(), from(sgo.getProvisioningState())));
+        return sgr.get();
+    }
+    
+    @Override
+    public void remove(StatefulGatewayObject object) throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public TargetDescriptor wrap(RepositoryObject object) {
+        if (object instanceof StatefulGatewayObject) {
+            StatefulGatewayObject sgo = (StatefulGatewayObject) object;
+            return new TargetDescriptor(sgo.getID(), from(sgo.getProvisioningState()));
+        }
+        throw new IllegalArgumentException();
+    }
+    
+    @Override
+    public StatefulGatewayObject unwrap(Descriptor descriptor) throws Exception {
+        StatefulGatewayRepository gr = Activator.getService(getThreadLocalRequest(), StatefulGatewayRepository.class);
+        List<StatefulGatewayObject> list = gr.get(Activator.getContext().createFilter("(" + GatewayObject.KEY_ID + "=" + descriptor.getName() + ")"));
+        if (list.size() == 1) {
+            return list.get(0);
+        }
+        throw new IllegalArgumentException();
+    }
+    
+    /**
+     * Helper method to find the {@link StatefulGatewayObject} for a given {@link GatewayObject}.
+     */
+    public StatefulGatewayObject findSGO(GatewayObject go) throws Exception {
+        StatefulGatewayRepository sgr = Activator.getService(getThreadLocalRequest(), StatefulGatewayRepository.class);
+        return sgr.get(Activator.getContext().createFilter("(" + GatewayObject.KEY_ID + "=" + go.getID() + ")")).get(0);
+    }
+    
+    /**
+     * Helper method to find all {@link StatefulGatewayObject}s for some {@link GatewayObject}s.
+     */
+    public List<StatefulGatewayObject> findSGOs(List<GatewayObject> gos) throws Exception {
+        List<StatefulGatewayObject> result = new ArrayList<StatefulGatewayObject>();
+        for (GatewayObject go : gos) {
+            result.add(findSGO(go));
         }
-        
-        return result.toArray(new TargetDescriptor[result.size()]);
+        return result;
     }
 }

Modified: incubator/ace/trunk/webui/war/webui.css
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/war/webui.css?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/war/webui.css (original)
+++ incubator/ace/trunk/webui/war/webui.css Wed Jul 15 22:16:11 2009
@@ -41,7 +41,24 @@
   color: red;
 }
 
+.objectpanel {
+  background-color: aliceblue;
+  margin: 4px 4px 4px 4px;
+}
+
+.objectpaneltext-selected {
+  color: white;
+}
+    
+.objectpanel-selected {
+  background-color: blue;
+}
+
+.objectpanel-related {
+  background-color: lightblue;
+}
+
 /* an 'add' button */
 .gwt-Button-add {
   width: 2em;
-}
\ No newline at end of file
+}

Modified: incubator/ace/trunk/webui/war/webui.html
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/webui/war/webui.html?rev=794436&r1=794435&r2=794436&view=diff
==============================================================================
--- incubator/ace/trunk/webui/war/webui.html (original)
+++ incubator/ace/trunk/webui/war/webui.html Wed Jul 15 22:16:11 2009
@@ -40,7 +40,7 @@
 
     <h1>Apache ACE</h1>
 
-    <table align="center">
+    <table align="center" border="1">
     <tr><td colspan="8" id="buttonPanel" /></tr>
     <tr>
         <th><h3 id="bundlesHeader">Bundles</h3></th>



Mime
View raw message