From f6df14b4ccefaebfa1f1ba1cfed2aa8cc67c5c6e Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Fri, 2 Nov 2012 13:51:27 +0000
Subject: [PATCH] SP-362 / BIS-246: Show metaproject tags in Web GUI and allow
 editing them when editing an entity - not existing metaprojects creation
 confirmation dialog

SVN: 27473
---
 .../web/client/ICommonClientService.java      |   5 +
 .../web/client/ICommonClientServiceAsync.java |   3 +
 .../client/web/client/application/Dict.java   |   6 +
 .../ui/AbstractRegistrationForm.java          |  25 ++--
 .../ui/widget/ButtonWithConfirmations.java    | 136 ++++++++++++++++++
 .../web/server/CommonClientService.java       |   7 +
 .../business/bo/AbstractBusinessObject.java   |   8 +-
 ...AbstractGenericEntityRegistrationForm.java |  86 +++++++++++
 ...AbstractGenericSampleRegisterEditForm.java |   4 +-
 .../cisd/openbis/public/common-dictionary.js  |   2 +
 10 files changed, 270 insertions(+), 12 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ButtonWithConfirmations.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index 41af5925927..433c4ce4ca8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -148,6 +148,11 @@ public interface ICommonClientService extends IClientService
     public TypedTableResultSet<Script> listScripts(ListScriptsCriteria criteria)
             throws UserFailureException;
 
+    /**
+     * Returns a list of all metaprojects.
+     */
+    public List<Metaproject> listMetaprojects() throws UserFailureException;
+
     /**
      * Returns a list of all metaprojects.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index 1c7562bd0d9..7bda8c87206 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -136,6 +136,9 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void listScripts(ListScriptsCriteria criteria,
             final AsyncCallback<TypedTableResultSet<Script>> asyncCallback);
 
+    /** @see ICommonClientService#listMetaprojects() */
+    public void listMetaprojects(final AsyncCallback<List<Metaproject>> asyncCallback);
+
     /** @see ICommonClientService#listMetaprojects(ListMetaprojectsCriteria) */
     public void listMetaprojects(ListMetaprojectsCriteria criteria,
             final AsyncCallback<TypedTableResultSet<Metaproject>> asyncCallback);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index 412f656059d..de33dd5e361 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -88,6 +88,12 @@ public abstract class Dict
 
     public static final String CHOOSE_METAPROJECT = "choose_metaproject";
 
+    public static final String CREATE_NOT_EXISTING_METAPROJECTS_CONFIRMATION_TITLE =
+            "create_not_existing_metaprojects_confirmation_title";
+
+    public static final String CREATE_NOT_EXISTING_METAPROJECTS_CONFIRMATION_MSG =
+            "create_not_existing_metaprojects_confirmation_msg";
+
     //
     // Form
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java
index 94517ac5848..6e2f01fbd97 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java
@@ -21,9 +21,7 @@ import java.util.List;
 
 import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
 import com.extjs.gxt.ui.client.Style.Scroll;
-import com.extjs.gxt.ui.client.event.BaseEvent;
 import com.extjs.gxt.ui.client.event.ButtonEvent;
-import com.extjs.gxt.ui.client.event.Events;
 import com.extjs.gxt.ui.client.event.FieldEvent;
 import com.extjs.gxt.ui.client.event.Listener;
 import com.extjs.gxt.ui.client.event.SelectionListener;
@@ -47,6 +45,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericCon
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.InfoBoxCallbackListener;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IComponentWithCloseConfirmation;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations.IConfirmation;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations.IConfirmationChain;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ConfirmationDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FormPanelWithSavePoint;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FormPanelWithSavePoint.DirtyChangeEvent;
@@ -96,7 +97,7 @@ public abstract class AbstractRegistrationForm extends ContentPanel implements
 
     protected final int fieldWidth;
 
-    protected Button saveButton;
+    protected ButtonWithConfirmations saveButton;
 
     private boolean sessionKeysInitiated = false;
 
@@ -252,7 +253,8 @@ public abstract class AbstractRegistrationForm extends ContentPanel implements
                 }
             });
 
-        saveButton = new Button(messageProvider.getMessage(Dict.BUTTON_SAVE));
+        saveButton = new ButtonWithConfirmations();
+        saveButton.setText(messageProvider.getMessage(Dict.BUTTON_SAVE));
         saveButton.setStyleAttribute("marginRight", "20px");
         saveButton.setId(getId() + SAVE_BUTTON);
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
@@ -366,17 +368,18 @@ public abstract class AbstractRegistrationForm extends ContentPanel implements
         addSaveButtonConfirmationListener(saveButton);
     }
 
-    protected void addSaveButtonConfirmationListener(final Button button)
+    protected void addSaveButtonConfirmationListener(final ButtonWithConfirmations button)
     {
-        button.addListener(Events.BeforeSelect, new Listener<BaseEvent>()
+        button.clearConfirmations();
+
+        button.addConfirmation(new IConfirmation()
             {
                 @Override
-                public void handleEvent(BaseEvent be)
+                public void confirm(final IConfirmationChain chain)
                 {
                     if (formPanel.isValid() && isDirtyCheckEnabled()
                             && formPanel.isDirtyForSavePoint() == false)
                     {
-                        be.setCancelled(true);
                         new ConfirmationDialog(messageProvider
                                 .getMessage(Dict.SAVE_UNCHANGED_FORM_CONFIRMATION_TITLE),
                                 messageProvider
@@ -385,10 +388,14 @@ public abstract class AbstractRegistrationForm extends ContentPanel implements
                                 @Override
                                 protected void onYes()
                                 {
-                                    button.fireEvent(Events.Select);
+                                    chain.next();
                                 }
                             }.show();
+                    } else
+                    {
+                        chain.next();
                     }
+
                 }
             });
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ButtonWithConfirmations.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ButtonWithConfirmations.java
new file mode 100644
index 00000000000..db447c04e89
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ButtonWithConfirmations.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.Events;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.widget.button.Button;
+
+/**
+ * @author pkupczyk
+ */
+public class ButtonWithConfirmations extends Button
+{
+
+    private ConfirmationChain confirmationChain;
+
+    public ButtonWithConfirmations()
+    {
+        confirmationChain = new ConfirmationChain(new IConfirmation()
+            {
+                @Override
+                public void confirm(IConfirmationChain chain)
+                {
+                    fireEvent(Events.Select);
+                }
+            });
+        addBeforeSelectListener();
+    }
+
+    public void addConfirmation(IConfirmation confirmation)
+    {
+        confirmationChain.add(confirmation);
+    }
+
+    public void clearConfirmations()
+    {
+        confirmationChain.clear();
+    }
+
+    @Override
+    public void removeAllListeners()
+    {
+        super.removeAllListeners();
+        addBeforeSelectListener();
+    }
+
+    private void addBeforeSelectListener()
+    {
+        addListener(Events.BeforeSelect, new Listener<BaseEvent>()
+            {
+                @Override
+                public void handleEvent(BaseEvent be)
+                {
+                    be.setCancelled(true);
+                    confirmationChain.reset();
+                    confirmationChain.next();
+                }
+            });
+    }
+
+    public static interface IConfirmation
+    {
+
+        public void confirm(IConfirmationChain chain);
+
+    }
+
+    public static interface IConfirmationChain
+    {
+
+        public void next();
+
+    }
+
+    private static class ConfirmationChain implements IConfirmationChain
+    {
+
+        private List<IConfirmation> confirmations = new ArrayList<IConfirmation>();
+
+        private IConfirmation lastConfirmation;
+
+        private int currentConfirmationIndex;
+
+        public ConfirmationChain(IConfirmation lastConfirmation)
+        {
+            this.lastConfirmation = lastConfirmation;
+        }
+
+        public void add(IConfirmation confirmation)
+        {
+            confirmations.add(confirmation);
+        }
+
+        public void clear()
+        {
+            confirmations.clear();
+            reset();
+        }
+
+        public void reset()
+        {
+            currentConfirmationIndex = 0;
+        }
+
+        @Override
+        public void next()
+        {
+            if (currentConfirmationIndex < confirmations.size())
+            {
+                confirmations.get(currentConfirmationIndex++).confirm(this);
+            } else
+            {
+                lastConfirmation.confirm(this);
+            }
+        }
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index f69bba1bb44..da39af9a86c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -682,6 +682,13 @@ public final class CommonClientService extends AbstractClientService implements
         return listEntities(scriptProvider, criteria);
     }
 
+    @Override
+    public List<Metaproject> listMetaprojects()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return commonServer.listMetaprojects(getSessionToken());
+    }
+
     @Override
     public TypedTableResultSet<Metaproject> listMetaprojects(ListMetaprojectsCriteria criteria)
             throws UserFailureException
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
index 7cde6fc6fe9..7648ff30ca0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
@@ -219,10 +219,14 @@ abstract class AbstractBusinessObject implements IDAOFactory
             MetaprojectPE metaproject =
                     getMetaprojectDAO().tryFindByOwnerAndName(session.getUserName(),
                             metaprojectsOrNullItem);
+
             if (metaproject == null)
             {
-                throw new UserFailureException("Metaproject '" + metaprojectsOrNullItem
-                        + "' couldn't be found.");
+                PersonPE owner = getPersonDAO().tryFindPersonByUserId(session.getUserName());
+                metaproject = new MetaprojectPE();
+                metaproject.setName(metaprojectsOrNullItem);
+                metaproject.setOwner(owner);
+                getMetaprojectDAO().createOrUpdateMetaproject(metaproject, owner);
             }
             metaprojects.add(metaproject);
         }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java
index 8b2cc4de8eb..39436dee985 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java
@@ -17,7 +17,9 @@
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -27,6 +29,7 @@ import com.extjs.gxt.ui.client.widget.form.FormPanel;
 import com.google.gwt.user.client.Element;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
@@ -38,6 +41,10 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.C
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.IChosenEntitiesListener;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MetaprojectArea;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MetaprojectChooserButton;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations.IConfirmation;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations.IConfirmationChain;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ConfirmationDialog;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdAndCodeHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
@@ -235,6 +242,85 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType
                     });
     }
 
+    @Override
+    protected void addSaveButtonConfirmationListener(ButtonWithConfirmations button)
+    {
+        super.addSaveButtonConfirmationListener(button);
+
+        button.addConfirmation(new IConfirmation()
+            {
+                @Override
+                public void confirm(final IConfirmationChain confirmationChain)
+                {
+                    String[] requestedMetaprojects = metaprojectArea.tryGetMetaprojects();
+
+                    if (formPanel.isValid() && requestedMetaprojects != null
+                            && requestedMetaprojects.length > 0)
+                    {
+                        viewContext.getCommonService().listMetaprojects(
+                                new CreateNonExistingMetaprojectsConfirmationCallback(viewContext,
+                                        confirmationChain, requestedMetaprojects));
+                    } else
+                    {
+                        confirmationChain.next();
+                    }
+                }
+            });
+    }
+
+    private static class CreateNonExistingMetaprojectsConfirmationCallback extends
+            AbstractAsyncCallback<List<Metaproject>>
+    {
+
+        private IConfirmationChain confirmationChain;
+
+        private String[] requestedMetaprojects;
+
+        public CreateNonExistingMetaprojectsConfirmationCallback(IViewContext<?> viewContext,
+                IConfirmationChain confirmationChain, String[] requestedMetaprojects)
+        {
+            super(viewContext);
+            this.confirmationChain = confirmationChain;
+            this.requestedMetaprojects = requestedMetaprojects;
+        }
+
+        @Override
+        protected void process(List<Metaproject> existingMetaprojects)
+        {
+            Set<String> notExistingMetaprojects = new LinkedHashSet<String>();
+            notExistingMetaprojects.addAll(Arrays.asList(requestedMetaprojects));
+
+            if (existingMetaprojects != null)
+            {
+                for (Metaproject existingMetaproject : existingMetaprojects)
+                {
+                    notExistingMetaprojects.remove(existingMetaproject.getName());
+                }
+            }
+
+            if (notExistingMetaprojects.isEmpty())
+            {
+                confirmationChain.next();
+            } else
+            {
+                new ConfirmationDialog(
+                        viewContext
+                                .getMessage(Dict.CREATE_NOT_EXISTING_METAPROJECTS_CONFIRMATION_TITLE),
+                        viewContext.getMessage(
+                                Dict.CREATE_NOT_EXISTING_METAPROJECTS_CONFIRMATION_MSG,
+                                notExistingMetaprojects))
+                    {
+                        @Override
+                        protected void onYes()
+                        {
+                            confirmationChain.next();
+                        }
+                    }.show();
+            }
+        }
+
+    }
+
     /**
      * Specifies if the code should be automatically generated.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
index fca0950ad52..1d5689206fa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
@@ -51,6 +51,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.S
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.SampleChooserField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.SampleChooserField.SampleChooserFieldAdaptor;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.file.AttachmentsFileFieldManager;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ButtonWithConfirmations;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo;
@@ -196,7 +197,8 @@ abstract public class AbstractGenericSampleRegisterEditForm extends
 
     private Button createSaveAndUploadButton()
     {
-        Button button = new Button(viewContext.getMessage(Dict.BUTTON_SAVE_AND_UPLOAD));
+        ButtonWithConfirmations button = new ButtonWithConfirmations();
+        button.setText(viewContext.getMessage(Dict.BUTTON_SAVE_AND_UPLOAD));
         addSaveButtonConfirmationListener(button);
         button.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index 991432d36d2..91889a4d153 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -64,6 +64,8 @@ var common = {
   metaprojects_hint: "List of metaprojects names separated by commas (\",\") or one metaproject name per line.",
   add_metaproject: "Add Metaproject...",
   choose_metaproject: "Choose a Metaproject",
+  create_not_existing_metaprojects_confirmation_title: "Confirm metaprojects creation",
+  create_not_existing_metaprojects_confirmation_msg: "Metaprojects {0} do not exist. Do you want to create them?",
   
   //
   // Form
-- 
GitLab