In Share Dialog, remove the header line when the permission list is empty.
authorChristos KK Loverdos <loverdos@gmail.com>
Mon, 15 Apr 2013 15:07:27 +0000 (18:07 +0300)
committerChristos KK Loverdos <loverdos@gmail.com>
Mon, 15 Apr 2013 15:07:27 +0000 (18:07 +0300)
Refs #3575

src/gr/grnet/pithos/web/client/Const.java
src/gr/grnet/pithos/web/client/FolderPermissionsDialog.java
src/gr/grnet/pithos/web/client/PermissionsList.java

index 6929476..3b5916f 100644 (file)
@@ -36,6 +36,7 @@ public final class Const {
     public static final String COMMA = ",";
     public static final String TILDE = "~";
     public static final String SEMI = ";";
+    public static final String COLON = ":";
     public static final String QUESTION_MARK = "?";
     public static final String AMPERSAND = "&";
 
@@ -45,6 +46,8 @@ public final class Const {
     public static final String UPDATE_EQ = "update=";
     public static final String QUESTION_MARK_UPDATE_EQ = QUESTION_MARK + UPDATE_EQ;
 
+    public static final String HTML_NBSP = "&nbsp;";
+
 
     public static final String NL = "\n";
 
@@ -56,4 +59,21 @@ public final class Const {
     public static String PurgeContainer(String name) {
         return "Purge Container [" + name + "]";
     }
+
+    public static String inSpan(String html) {
+        return "<span>" + html + "</span>";
+    }
+
+    public static String inSpan(String html0, String html1, String ...html) {
+        final int knownLength = html0.length() + html1.length();
+        final int estimatedLength = knownLength * html.length;
+        final StringBuilder sb = new StringBuilder(estimatedLength);
+        sb.append(html0);
+        sb.append(html1);
+        for(String s : html) {
+            sb.append(s);
+        }
+
+        return inSpan(sb.toString());
+    }
 }
index e44bb00..4eef837 100644 (file)
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
-import gr.grnet.pithos.web.client.foldertree.Folder;\r
-import gr.grnet.pithos.web.client.rest.PostRequest;\r
-import gr.grnet.pithos.web.client.rest.PutRequest;\r
-import gr.grnet.pithos.web.client.rest.RestException;\r
-\r
-import java.util.Map;\r
-\r
 import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.core.client.Scheduler;\r
 import com.google.gwt.dom.client.NativeEvent;\r
@@ -52,13 +45,13 @@ import com.google.gwt.http.client.Response;
 import com.google.gwt.http.client.URL;\r
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.Event.NativePreviewEvent;\r
-import com.google.gwt.user.client.ui.Anchor;\r
-import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.DialogBox;\r
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
-import com.google.gwt.user.client.ui.HorizontalPanel;\r
-import com.google.gwt.user.client.ui.Label;\r
-import com.google.gwt.user.client.ui.VerticalPanel;\r
+import com.google.gwt.user.client.ui.*;\r
+import gr.grnet.pithos.web.client.foldertree.Folder;\r
+import gr.grnet.pithos.web.client.rest.PostRequest;\r
+import gr.grnet.pithos.web.client.rest.PutRequest;\r
+import gr.grnet.pithos.web.client.rest.RestException;\r
+\r
+import java.util.Map;\r
 \r
 /**\r
  * The 'Folder properties' dialog box implementation.\r
@@ -67,51 +60,55 @@ public class FolderPermissionsDialog extends DialogBox {
 \r
     protected Pithos app;\r
 \r
-       /**\r
-        * The widget that holds the folderName of the folder.\r
-        */\r
-       Label folderName = new Label();\r
+    /**\r
+     * The widget that holds the folderName of the folder.\r
+     */\r
+    Label folderName = new Label();\r
+\r
+    protected PermissionsList permList;\r
+\r
+    final Folder folder;\r
 \r
-       protected PermissionsList permList;\r
+    final VerticalPanel inner;\r
 \r
-       final Folder folder;\r
+    final Button updateButton;\r
 \r
-       final VerticalPanel inner;\r
+    private boolean _initialPermissionCheck = true;\r
 \r
-       /**\r
-        * The widget's constructor.\r
-        */\r
-       public FolderPermissionsDialog(final Pithos app, Folder selected) {\r
+    /**\r
+     * The widget's constructor.\r
+     */\r
+    public FolderPermissionsDialog(final Pithos app, Folder selected) {\r
         this.app = app;\r
-               Anchor close = new Anchor("close");\r
-               close.addStyleName("close");\r
-               close.addClickHandler(new ClickHandler() {\r
-                       \r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               hide();\r
-                       }\r
-               });\r
+        Anchor close = new Anchor("close");\r
+        close.addStyleName("close");\r
+        close.addClickHandler(new ClickHandler() {\r
 \r
-               setGlassEnabled(true);\r
-               setStyleName("pithos-DialogBox");\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                hide();\r
+            }\r
+        });\r
 \r
-               // Enable IE selection for the dialog (must disable it upon closing it)\r
-               Pithos.enableIESelection();\r
+        setGlassEnabled(true);\r
+        setStyleName("pithos-DialogBox");\r
 \r
-               folder = selected;\r
+        // Enable IE selection for the dialog (must disable it upon closing it)\r
+        Pithos.enableIESelection();\r
 \r
-               setText("Folder permissions");\r
+        folder = selected;\r
 \r
-               // Outer contains inner and buttons\r
-               VerticalPanel outer = new VerticalPanel();\r
-               outer.add(close);\r
-               // Inner contains generalPanel and permPanel\r
-               inner = new VerticalPanel();\r
-               inner.addStyleName("inner");\r
+        setText("Folder permissions");\r
 \r
+        // Outer contains inner and buttons\r
+        VerticalPanel outer = new VerticalPanel();\r
+        outer.add(close);\r
+        // Inner contains generalPanel and permPanel\r
+        inner = new VerticalPanel();\r
+        inner.addStyleName("inner");\r
 \r
-               folderName.setText(folder.getName());\r
+\r
+        folderName.setText(folder.getName());\r
 \r
         VerticalPanel permPanel = new VerticalPanel();\r
         FileShareDialog.PrivateSharingImages images = GWT.create(FileShareDialog.PrivateSharingImages.class);\r
@@ -124,6 +121,7 @@ public class FolderPermissionsDialog extends DialogBox {
             public void onClick(ClickEvent event) {\r
                 PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);\r
                 dlg.center();\r
+                checkUpdateButtonVisibility();\r
             }\r
         });\r
         addUser.addStyleName("button");\r
@@ -133,22 +131,24 @@ public class FolderPermissionsDialog extends DialogBox {
         Button add = new Button("Add Group", new ClickHandler() {\r
             @Override\r
             public void onClick(ClickEvent event) {\r
-               if (app.getAccount().getGroups().isEmpty()) {\r
+                if(app.getAccount().getGroups().isEmpty()) {\r
                     new GroupCreateDialog(app, new Command() {\r
-                                               \r
-                                               @Override\r
-                                               public void execute() {\r
-                                       if (app.getAccount().getGroups().isEmpty())\r
-                                               return;\r
-                                       PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
-                                       dlg.center();\r
-                                               }\r
-                                       }).center();\r
-               }\r
-               else {\r
-                       PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
-                       dlg.center();\r
-               }\r
+                        @Override\r
+                        public void execute() {\r
+                            if(app.getAccount().getGroups().isEmpty()) {\r
+                                return;\r
+                            }\r
+                            PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                            dlg.center();\r
+                            checkUpdateButtonVisibility();\r
+                        }\r
+                    }).center();\r
+                }\r
+                else {\r
+                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                    dlg.center();\r
+                    checkUpdateButtonVisibility();\r
+                }\r
             }\r
         });\r
         add.addStyleName("button");\r
@@ -162,154 +162,178 @@ public class FolderPermissionsDialog extends DialogBox {
 \r
         outer.add(inner);\r
 \r
-               // Create the 'Create/Update' button, along with a listener that hides the dialog\r
-               // when the button is clicked and quits the application.\r
-               String okLabel = "Update";\r
-               final Button ok = new Button(okLabel, new ClickHandler() {\r
-                       @Override\r
-                       public void onClick(ClickEvent event) {\r
-                               updateFolder();\r
-                               closeDialog();\r
-                       }\r
-               });\r
-               ok.addStyleName("button");\r
-               outer.add(ok);\r
+        // Create the 'Create/Update' button, along with a listener that hides the dialog\r
+        // when the button is clicked and quits the application.\r
+        final String okLabel = "Update";\r
+        updateButton = new Button(okLabel, new ClickHandler() {\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                updateFolder();\r
+                closeDialog();\r
+            }\r
+        });\r
+        updateButton.addStyleName("button");\r
+        checkUpdateButtonVisibility();\r
+        outer.add(updateButton);\r
         outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
         setWidget(outer);\r
-       }\r
-\r
-       @Override\r
-       protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
-               super.onPreviewNativeEvent(preview);\r
-\r
-               NativeEvent evt = preview.getNativeEvent();\r
-               if (evt.getType().equals(KeyDownEvent.getType().getName()))\r
-                       // Use the popup's key preview hooks to close the dialog when either\r
-                       // enter or escape is pressed.\r
-                       switch (evt.getKeyCode()) {\r
-                               case KeyCodes.KEY_ENTER:\r
-                                       updateFolder();\r
+    }\r
+\r
+    private void checkUpdateButtonVisibility() {\r
+        if(!this._initialPermissionCheck) {\r
+            updateButton.setVisible(true);\r
+            return;\r
+        }\r
+\r
+        updateButton.setVisible(permList.hasPermissions());\r
+\r
+        this._initialPermissionCheck = false;\r
+    }\r
+\r
+    @Override\r
+    protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
+        super.onPreviewNativeEvent(preview);\r
+\r
+        NativeEvent evt = preview.getNativeEvent();\r
+        if(evt.getType().equals(KeyDownEvent.getType().getName()))\r
+        // Use the popup's key preview hooks to close the dialog when either\r
+        // enter or escape is pressed.\r
+        {\r
+            switch(evt.getKeyCode()) {\r
+                case KeyCodes.KEY_ENTER:\r
+                    updateFolder();\r
                     closeDialog();\r
-                                       break;\r
-                               case KeyCodes.KEY_ESCAPE:\r
-                                       closeDialog();\r
-                                       break;\r
-                       }\r
-       }\r
-\r
-\r
-       /**\r
-        * Enables IE selection prevention and hides the dialog\r
-        * (we disable the prevention on creation of the dialog)\r
-        */\r
-       public void closeDialog() {\r
-               Pithos.preventIESelection();\r
-               hide();\r
-       }\r
-\r
-       void updateFolder() {\r
+                    break;\r
+                case KeyCodes.KEY_ESCAPE:\r
+                    closeDialog();\r
+                    break;\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Enables IE selection prevention and hides the dialog\r
+     * (we disable the prevention on creation of the dialog)\r
+     */\r
+    public void closeDialog() {\r
+        Pithos.preventIESelection();\r
+        hide();\r
+    }\r
+\r
+    void updateFolder() {\r
         final Map<String, Boolean[]> perms = (permList.hasChanges() ? permList.getPermissions() : null);\r
-        updateMetadata(folder.getUri() + "?update=", perms);\r
-       }\r
+        updateMetadata(\r
+            folder.getUri() + Const.QUESTION_MARK_UPDATE_EQ,\r
+            perms\r
+        );\r
+    }\r
 \r
-       protected void updateMetadata(final String path, final Map<String, Boolean[]> newPermissions) {\r
-        if (newPermissions != null) {\r
+    protected void updateMetadata(final String path, final Map<String, Boolean[]> newPermissions) {\r
+        if(newPermissions != null) {\r
             PostRequest updateFolder = new PostRequest(app.getApiPath(), folder.getOwnerID(), path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
                     app.updateFolder(folder.getParent(), false, new Command() {\r
-                                               \r
-                                               @Override\r
-                                               public void execute() {\r
-                                                       app.updateMySharedRoot();\r
-                                               }\r
-                                       }, true);\r
+                        @Override\r
+                        public void execute() {\r
+                            app.updateMySharedRoot();\r
+                        }\r
+                    }, true);\r
                 }\r
 \r
                 @Override\r
                 public void onError(Throwable t) {\r
-                    GWT.log("", t);\r
-                                       app.setError(t);\r
-                    if (t instanceof RestException) {\r
-                       if (((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) { //Probably a virtual folder\r
+                    app.setError(t);\r
+                    if(t instanceof RestException) {\r
+                        if(((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) { //Probably a virtual folder\r
                             final String path1 = folder.getUri();\r
                             PutRequest newFolder = new PutRequest(app.getApiPath(), folder.getOwnerID(), path1) {\r
                                 @Override\r
                                 public void onSuccess(Resource result) {\r
-                                       updateMetadata(path, newPermissions);\r
+                                    updateMetadata(path, newPermissions);\r
                                 }\r
 \r
                                 @Override\r
                                 public void onError(Throwable _t) {\r
-                                    GWT.log("", _t);\r
-                                                       app.setError(_t);\r
-                                    if(_t instanceof RestException){\r
+                                    app.setError(_t);\r
+                                    if(_t instanceof RestException) {\r
                                         app.displayError("Unable to update folder: " + ((RestException) _t).getHttpStatusText());\r
                                     }\r
-                                    else\r
+                                    else {\r
                                         app.displayError("System error modifying folder: " + _t.getMessage());\r
+                                    }\r
                                 }\r
 \r
-                                               @Override\r
-                                               protected void onUnauthorized(Response response) {\r
-                                                       app.sessionExpired();\r
-                                               }\r
+                                @Override\r
+                                protected void onUnauthorized(Response response) {\r
+                                    app.sessionExpired();\r
+                                }\r
                             };\r
                             newFolder.setHeader("X-Auth-Token", app.getUserToken());\r
                             newFolder.setHeader("Content-Type", "application/folder");\r
                             newFolder.setHeader("Accept", "*/*");\r
                             newFolder.setHeader("Content-Length", "0");\r
                             Scheduler.get().scheduleDeferred(newFolder);\r
-                       }\r
-                       else if (((RestException) t).getHttpStatusCode() == Response.SC_CONFLICT) {\r
-                               app.displayError("Cannot set permissions. Probably subfolders or files already have permissions set");\r
-                       }\r
-                       else\r
-                               app.displayError("Εrror modifying folder: " + t.getMessage());\r
+                        }\r
+                        else if(((RestException) t).getHttpStatusCode() == Response.SC_CONFLICT) {\r
+                            app.displayError("Cannot set permissions. Probably subfolders or files already have permissions set");\r
+                        }\r
+                        else {\r
+                            app.displayError("Εrror modifying folder: " + t.getMessage());\r
+                        }\r
+                    }\r
+                    else {\r
+                        app.displayError("System error modifying folder: " + t.getMessage());\r
                     }\r
-                    else\r
-                       app.displayError("System error modifying folder: " + t.getMessage());\r
                 }\r
 \r
-                               @Override\r
-                               protected void onUnauthorized(Response response) {\r
-                                       app.sessionExpired();\r
-                               }\r
+                @Override\r
+                protected void onUnauthorized(Response response) {\r
+                    app.sessionExpired();\r
+                }\r
             };\r
             updateFolder.setHeader("X-Auth-Token", app.getUserToken());\r
             String readPermHeader = "read=";\r
             String writePermHeader = "write=";\r
-            for (String u : newPermissions.keySet()) {\r
+            for(String u : newPermissions.keySet()) {\r
                 Boolean[] p = newPermissions.get(u);\r
-                if (p[0] != null && p[0])\r
+                if(p[0] != null && p[0]) {\r
                     readPermHeader += u + ",";\r
-                if (p[1] != null && p[1])\r
+                }\r
+                if(p[1] != null && p[1]) {\r
                     writePermHeader += u + ",";\r
+                }\r
             }\r
-            if (readPermHeader.endsWith("="))\r
+            if(readPermHeader.endsWith("=")) {\r
                 readPermHeader = "";\r
-            else if (readPermHeader.endsWith(","))\r
+            }\r
+            else if(readPermHeader.endsWith(",")) {\r
                 readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);\r
-            if (writePermHeader.endsWith("="))\r
+            }\r
+            if(writePermHeader.endsWith("=")) {\r
                 writePermHeader = "";\r
-            else if (writePermHeader.endsWith(","))\r
+            }\r
+            else if(writePermHeader.endsWith(",")) {\r
                 writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);\r
-            String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;\r
-            if (permHeader.length() == 0)\r
+            }\r
+            String permHeader = readPermHeader + ((readPermHeader.length() > 0 && writePermHeader.length() > 0) ? ";" : "") + writePermHeader;\r
+            if(permHeader.length() == 0) {\r
                 permHeader = "~";\r
-            else\r
-               permHeader = URL.encodePathSegment(permHeader);\r
+            }\r
+            else {\r
+                permHeader = URL.encodePathSegment(permHeader);\r
+            }\r
             updateFolder.setHeader("X-Object-Sharing", permHeader);\r
             Scheduler.get().scheduleDeferred(updateFolder);\r
         }\r
-        else\r
+        else {\r
             app.updateFolder(folder.getParent(), false, new Command() {\r
-                               \r
-                               @Override\r
-                               public void execute() {\r
-                                       app.updateMySharedRoot();\r
-                               }\r
-                       }, true);\r
+                @Override\r
+                public void execute() {\r
+                    app.updateMySharedRoot();\r
+                }\r
+            }, true);\r
+        }\r
     }\r
 }\r
index a725cfb..e7e65ae 100644 (file)
  */
 package gr.grnet.pithos.web.client;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.RadioButton;
-import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.*;
 import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
 import gr.grnet.pithos.web.client.catalog.UserCatalogs;
 
+import java.util.HashMap;
+import java.util.Map;
+
 
 public class PermissionsList extends Composite {
 
-       Map<String, Boolean[]> permissions = null;
-       
-       final FileShareDialog.PrivateSharingImages images;
-       
-       final VerticalPanel permPanel = new VerticalPanel();
-       
-       final FlexTable permTable = new FlexTable();
-       
-       final String owner;
-       
-       protected boolean hasChanges = false;
+    Map<String, Boolean[]> permissions = null;
+
+    final FileShareDialog.PrivateSharingImages images;
+
+    final VerticalPanel permPanel = new VerticalPanel();
+
+    final FlexTable permTable = new FlexTable();
+
+    final String owner;
+
+    protected boolean hasChanges = false;
 
     private boolean readonly = false;
-    
+
     Command changePermissionsCallback;
 
     private final Pithos app;
-       
-       public PermissionsList(Pithos app, final FileShareDialog.PrivateSharingImages theImages, Map<String, Boolean[]> thePermissions, String theOwner, boolean inheritsPermissions, Command _changePermissionsCallback){
+
+    public PermissionsList(
+        Pithos app,
+        final FileShareDialog.PrivateSharingImages theImages,
+        Map<String, Boolean[]> thePermissions,
+        String theOwner,
+        boolean inheritsPermissions,
+        Command _changePermissionsCallback
+    ) {
         this.app = app;
-               changePermissionsCallback = _changePermissionsCallback;
-               images = theImages;
-               owner = theOwner;
-               permissions =  new HashMap<String, Boolean[]>(thePermissions);
-               permTable.setText(0, 0, "Users/Groups");
-               permTable.setText(0, 1, "Read Only");
-               permTable.setText(0, 2, "Read/Write");
-               permTable.setText(0, 3, "");
-               permTable.getFlexCellFormatter().setStyleName(0, 0, "props-toplabels");
-               permTable.getFlexCellFormatter().setStyleName(0, 1, "props-toplabels");
-               permTable.getFlexCellFormatter().setStyleName(0, 2, "props-toplabels");
-               permTable.getFlexCellFormatter().setStyleName(0, 3, "props-toplabels");
-               permPanel.add(permTable);
-               permPanel.addStyleName("pithos-TabPanelBottom");
-               initWidget(permPanel);
-               updatePermissionTable();
-       }
-
-       public boolean hasChanges(){
-               return hasChanges;
-       }
-
-       /**
-        * Retrieve the permissions.
-        *
-        * @return the permissions
-        */
-       public Map<String, Boolean[]> getPermissions() {
-               return permissions;
-       }
-
-       public void addPermission(String userID, boolean read, boolean write){
-               permissions.put(userID, new Boolean[] {Boolean.valueOf(read), Boolean.valueOf(write)});
-               hasChanges = true;
+        changePermissionsCallback = _changePermissionsCallback;
+        images = theImages;
+        owner = theOwner;
+        permissions = new HashMap<String, Boolean[]>(thePermissions);
+        updatePermissionsHeader();
+        permPanel.add(permTable);
+        permPanel.addStyleName("pithos-TabPanelBottom");
+        initWidget(permPanel);
         updatePermissionTable();
-        if (changePermissionsCallback != null)
-               changePermissionsCallback.execute();
-       }
-
-       /**
-        * Shows the permission table 
-        * 
-        */
-       void updatePermissionTable(){
-               int i = 1;
+    }
+
+    private void updatePermissionsHeader() {
+        if(hasPermissions()) {
+            permTable.setText(0, 0, "Users/Groups");
+            permTable.setText(0, 1, "Read Only");
+            permTable.setText(0, 2, "Read/Write");
+            permTable.setText(0, 3, "");
+            permTable.getFlexCellFormatter().setStyleName(0, 0, "props-toplabels");
+            permTable.getFlexCellFormatter().setStyleName(0, 1, "props-toplabels");
+            permTable.getFlexCellFormatter().setStyleName(0, 2, "props-toplabels");
+            permTable.getFlexCellFormatter().setStyleName(0, 3, "props-toplabels");
+        }
+        else {
+            permTable.setText(0, 0, "");
+            permTable.setText(0, 1, "");
+            permTable.setText(0, 2, "");
+            permTable.setText(0, 3, "");
+        }
+    }
+
+    public boolean hasPermissions() {
+        return permissionCount() > 0;
+    }
+
+    public int permissionCount() {
+        return permissions == null
+            ? 0
+            : permissions.size();
+    }
+
+    public boolean hasChanges() {
+        return hasChanges;
+    }
+
+    /**
+     * Retrieve the permissions.
+     *
+     * @return the permissions
+     */
+    public Map<String, Boolean[]> getPermissions() {
+        return permissions;
+    }
+
+    public void addPermission(String userID, boolean read, boolean write) {
+        permissions.put(userID, new Boolean[]{Boolean.valueOf(read), Boolean.valueOf(write)});
+        hasChanges = true;
+        updatePermissionTable();
+        if(changePermissionsCallback != null) {
+            changePermissionsCallback.execute();
+        }
+    }
+
+    private boolean isGroup(String userID) {
+        return userID.contains(Const.COLON);
+    }
+
+    /**
+     * Shows the permission table
+     */
+    void updatePermissionTable() {
+        int i = 1;
         final int ii = i;
-        for (int j=1; j<permTable.getRowCount(); j++)
+        for(int j = 1; j < permTable.getRowCount(); j++) {
             permTable.removeRow(j);
-               for(final String userID : permissions.keySet()) {
-            if (!userID.contains(":")) {
-                 //not a group
+        }
+
+        updatePermissionsHeader();
+
+        for(final String userID : permissions.keySet()) {
+            if(!isGroup(userID)) {
                 final String displayName = app.getDisplayNameForUserID(userID);
                 if(displayName != null) {
                     permTable.setHTML(
                         i,
                         0,
-                        "<span>" + AbstractImagePrototype.create(images.permUser()).getHTML() + "&nbsp;" + displayName + "</span>"
+                        Const.inSpan(
+                            AbstractImagePrototype.create(
+                                images.permUser()).getHTML() +
+                                Const.HTML_NBSP +
+                                displayName
+                        )
                     );
                 }
                 else {
@@ -142,14 +177,28 @@ public class PermissionsList extends Composite {
                             permTable.setHTML(
                                 ii,
                                 0,
-                                "<span>" + AbstractImagePrototype.create(images.permUser()).getHTML() + "&nbsp;" + displayName + "</span>"
+                                Const.inSpan(
+                                    AbstractImagePrototype.create(
+                                        images.permUser()).getHTML() +
+                                        Const.HTML_NBSP +
+                                        displayName
+                                )
                             );
                         }
                     }.scheduleDeferred();
                 }
             }
             else {
-                permTable.setHTML(i, 0, "<span>" + AbstractImagePrototype.create(images.permGroup()).getHTML() + "&nbsp;" + userID.split(":")[1].trim() + "</span>");
+                permTable.setHTML(
+                    i,
+                    0,
+                    Const.inSpan(
+                        AbstractImagePrototype.create(
+                            images.permGroup()).getHTML() +
+                            Const.HTML_NBSP +
+                            userID.split(Const.COLON)[1].trim()
+                    )
+                );
             }
             permTable.getFlexCellFormatter().setStyleName(i, 0, "props-values");
 
@@ -157,8 +206,8 @@ public class PermissionsList extends Composite {
             Boolean readP = userPerms[0];
             Boolean writeP = userPerms[1];
 
-                       RadioButton read = new RadioButton("permissions" + i);
-                       read.setValue(readP != null ? readP : false);
+            RadioButton read = new RadioButton("permissions" + i);
+            read.setValue(readP != null ? readP : false);
             permTable.setWidget(i, 1, read);
             permTable.getFlexCellFormatter().setHorizontalAlignment(i, 1, HasHorizontalAlignment.ALIGN_CENTER);
 
@@ -167,7 +216,7 @@ public class PermissionsList extends Composite {
             permTable.setWidget(i, 2, write);
             permTable.getFlexCellFormatter().setHorizontalAlignment(i, 2, HasHorizontalAlignment.ALIGN_CENTER);
 
-            if (!readonly) {
+            if(!readonly) {
                 read.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
                     @Override
                     public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) {
@@ -175,8 +224,9 @@ public class PermissionsList extends Composite {
                         ps[0] = booleanValueChangeEvent.getValue();
                         ps[1] = !booleanValueChangeEvent.getValue();
                         hasChanges = true;
-                        if (changePermissionsCallback != null)
-                               changePermissionsCallback.execute();
+                        if(changePermissionsCallback != null) {
+                            changePermissionsCallback.execute();
+                        }
                     }
                 });
                 write.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@@ -186,8 +236,9 @@ public class PermissionsList extends Composite {
                         ps[0] = !booleanValueChangeEvent.getValue();
                         ps[1] = booleanValueChangeEvent.getValue();
                         hasChanges = true;
-                        if (changePermissionsCallback != null)
-                               changePermissionsCallback.execute();
+                        if(changePermissionsCallback != null) {
+                            changePermissionsCallback.execute();
+                        }
                     }
                 });
                 Anchor removeButton = new Anchor("remove");
@@ -198,8 +249,9 @@ public class PermissionsList extends Composite {
                         permissions.remove(userID);
                         updatePermissionTable();
                         hasChanges = true;
-                        if (changePermissionsCallback != null)
-                               changePermissionsCallback.execute();
+                        if(changePermissionsCallback != null) {
+                            changePermissionsCallback.execute();
+                        }
                     }
                 });
                 permTable.setWidget(i, 3, removeButton);
@@ -209,7 +261,7 @@ public class PermissionsList extends Composite {
                 read.setEnabled(false);
                 write.setEnabled(false);
             }
-                       i++;
-               }
-       }
+            i++;
+        }
+    }
 }