diff --git a/openbis/.classpath b/openbis/.classpath index 5af6c9a7054f9a91316a6e0fe384155e407bee85..3e4790c9145ae49dc48b00904f1087a74a0e3abc 100644 --- a/openbis/.classpath +++ b/openbis/.classpath @@ -61,6 +61,7 @@ <classpathentry kind="lib" path="/libraries/poi/poi-ooxml-3.7-20101029.jar"/> <classpathentry kind="lib" path="/libraries/poi/poi-ooxml-schemas-3.7-20101029.jar"/> <classpathentry kind="lib" path="/libraries/gwt-image-loader/gwt-image-loader.jar"/> + <classpathentry kind="lib" path="/libraries/mail/mail.jar"/> <classpathentry kind="lib" path="/libraries/jackson/jackson-core-asl.jar"/> <classpathentry kind="lib" path="/libraries/jackson/jackson-mapper-asl.jar"/> <classpathentry kind="lib" path="/libraries/jsonrpc4j/jsonrpc4j.jar"/> 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 6d54a0a50cde0e701da069586e5bd5f987d27fab..bdae38d757459bbd4c06e640d5a214979f40184e 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 @@ -694,6 +694,8 @@ public abstract class Dict public static final String MENU_ARCHIVING = "menu_archiving"; + public static final String MENU_GENERAL_IMPORT = "menu_general_import"; + // // Tab Titles // @@ -734,6 +736,8 @@ public abstract class Dict public static final String CONFIRM_CLOSE_MSG = "confirm_close_msg"; + public static final String GENERAL_IMPORT = "general_import"; + // // Role View // @@ -1056,7 +1060,7 @@ public abstract class Dict public static final String FILE_TEMPLATE_LABEL = "file_template_label"; public static final String UPDATE_EXISTING_ENTITIES_LABEL = "update_existing_entities_label"; - + public static final String URL = "url"; public static final String REASON = "reason"; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java index 326ca8e8905d2655d9f5fa18795f01599f36d6de..adc2bb9cebb88002d85bd4d88453537d5d826039 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java @@ -22,10 +22,12 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs import ch.systemsx.cisd.openbis.generic.client.web.client.application.ActionContext; import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent; import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier; import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageAction; import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageDomain; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AuthorizationGroupGrid; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GeneralImportComponent; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PersonGrid; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignmentGrid; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.SpaceGrid; @@ -1517,6 +1519,45 @@ public final class ComponentProvider }; } + public AbstractTabItemFactory createGeneralImport() + { + return new AbstractTabItemFactory() + { + @Override + public ITabItem create() + { + TabContent libraryImportTab = new GeneralImportComponent(viewContext); + return createRegistrationTab(getTabTitle(), + DatabaseModificationAwareComponent.wrapUnaware(libraryImportTab)); + } + + @Override + public String getId() + { + return GeneralImportComponent.createId(); + } + + @Override + public HelpPageIdentifier getHelpPageIdentifier() + { + return new HelpPageIdentifier(HelpPageDomain.GENERAL_IMPORT, + HelpPageAction.IMPORT); + } + + @Override + public String getTabTitle() + { + return GeneralImportComponent.getTabTitle(viewContext); + } + + @Override + public String tryGetLink() + { + return null; + } + }; + } + public IMainPanel tryGetMainTabPanel() { return mainTabPanelOrNull; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java index 38306e8634d9aeb89e6e80fa68150341b0a1f237..dcca2a31db4a361f4e7e2df348a00cfe57bc929e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java @@ -62,6 +62,9 @@ public class HelpPageIdentifier FILE_TYPE(ADMINISTRATION), AUTHORIZATION(ADMINISTRATION), + + GENERAL_IMPORT(ADMINISTRATION), + // authorization subdomains USERS(AUTHORIZATION), ROLES(AUTHORIZATION), AUTHORIZATION_GROUPS(AUTHORIZATION), diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java index 1be451d3979869add42b747189ba376e053001c3..109587f6a084910bf7c48331a9812417a2113e7b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java @@ -79,7 +79,7 @@ public class TopMenu extends LayoutContainer USER_MENU_CHANGE_SETTINGS, USER_MENU_LOGOUT, USER_MENU_LOGIN, - VOCABULARY_MENU_BROWSE, VOCABULARY_MENU_NEW; + VOCABULARY_MENU_BROWSE, VOCABULARY_MENU_NEW, GENERAL_IMPORT_MENU; public String getMenuId() { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java index e20df7990c37477cf8dd22212302b62f04f4aeba..c446ead8c9a2e59e35eb3508c105b0b917b13e05 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java @@ -51,6 +51,8 @@ public class AdministrationMenu extends TopMenuItem submenu.add(new AuthorizationMenu(messageProvider, componentProvider)); submenu.add(new ActionMenu(TopMenu.ActionMenuKind.DATA_SET_MENU_FILE_FORMATS, messageProvider, componentProvider.getFileFormatTypeBrowser())); + submenu.add(new ActionMenu(TopMenu.ActionMenuKind.GENERAL_IMPORT_MENU, messageProvider, + componentProvider.createGeneralImport())); if (viewContext.isLoggingEnabled()) { submenu.add(new ActionMenu(TopMenu.ActionMenuKind.LOGGING_CONSOLE, messageProvider, diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GeneralImportComponent.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GeneralImportComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..77240e0f69817e445015cf70b5da0e05335ce91f --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GeneralImportComponent.java @@ -0,0 +1,59 @@ +package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui; + +import com.google.gwt.user.client.ui.Widget; + +import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; +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; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType; + +/** + * Allows to specify search criteria for materials contained in wells. Used in experiment section + * panel or as a standalone module. + * + * @author Pawel Glyzewski + */ +public class GeneralImportComponent extends TabContent +{ + private static final String PREFIX = "general-import"; + + public static final String SESSION_KEY = PREFIX; + + public static final String createId() + { + return GenericConstants.ID_PREFIX + SESSION_KEY; + } + + private final Widget genericImportForm; + + public static String getTabTitle(IViewContext<ICommonClientServiceAsync> viewContext) + { + return viewContext.getMessage(Dict.GENERAL_IMPORT); + } + + public GeneralImportComponent(IViewContext<ICommonClientServiceAsync> viewContext) + { + super(getTabTitle(viewContext), viewContext, null); + + SampleType sampleType = new SampleType(); + sampleType + .setCode(ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType.DEFINED_IN_FILE); + this.genericImportForm = + viewContext.getClientPluginFactoryProvider() + .getClientPluginFactory(EntityKind.SAMPLE, sampleType) + .createClientPlugin(null).createBatchRegistrationForEntityType(null); + + setContentVisible(true); + } + + @Override + protected void showContent() + { + removeAll(); + add(genericImportForm); + layout(); + } +} \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java index ca3e2fd60f42650e57cb3317824752faa5361437..a926344e7cafcc51ebc45221ba403fcb412cc290 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java @@ -40,7 +40,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session; */ abstract class AbstractCommonServer<T extends IServer> extends AbstractServer<T> { - private final IAuthenticationService authenticationService; protected final ICommonBusinessObjectFactory businessObjectFactory; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java index c31acbdb9605c51688b0888a86c06c8124a5e580..11a19af0e2b699ad0a8ec9c69a959630f501317b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java @@ -16,12 +16,17 @@ package ch.systemsx.cisd.openbis.generic.server; +import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import javax.annotation.Resource; @@ -32,6 +37,9 @@ import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.authentication.Principal; import ch.systemsx.cisd.common.exceptions.InvalidSessionException; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.mail.IMailClient; +import ch.systemsx.cisd.common.mail.MailClient; +import ch.systemsx.cisd.common.mail.MailClientParameters; import ch.systemsx.cisd.common.spring.AbstractServiceWithLogger; import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager; import ch.systemsx.cisd.openbis.generic.server.business.PropertiesBatchManager; @@ -77,6 +85,9 @@ import ch.systemsx.cisd.openbis.generic.shared.util.ServerUtils; */ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> implements IServer { + protected static ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 10, 360, + TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); + private final static String ETL_SERVER_USERNAME_PREFIX = "etlserver"; protected static final class AuthenticatedPersonBasedPrincipalProvider implements @@ -120,6 +131,9 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp @Resource(name = ComponentNames.REMOTE_HOST_VALIDATOR) private IRemoteHostValidator remoteHostValidator; + @Resource(name = ResourceNames.MAIL_CLIENT_PARAMETERS) + protected MailClientParameters mailClientParameters; + private IPropertiesBatchManager propertiesBatchManager; private String userForAnonymousLogin; @@ -629,4 +643,47 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp } } + protected void executeASync(final String userEmail, final IASyncAction action) + { + final IMailClient mailClient = new MailClient(mailClientParameters); + Runnable task = new Runnable() + { + public void run() + { + StringWriter writer = new StringWriter(); + boolean success = true; + Date startDate = new Date(); + try + { + success = action.doAction(writer); + } catch (RuntimeException e) + { + operationLog.error("Asynchronous action '" + action.getName() + + "' failed. ", e); + success = false; + } finally + { + sendEmail(mailClient, writer.toString(), + getSubject(action.getName(), startDate, success), userEmail); + } + } + }; + executor.submit(task); + } + + private void sendEmail(IMailClient mailClient, String content, String subject, String recipient) + { + mailClient.sendMessage(subject, content, null, null, recipient); + } + + private static String getSubject(String actionName, Date startDate, boolean success) + { + return addDate(actionName + " " + (success ? "successfully performed" : "failed"), + startDate); + } + + private static String addDate(String subject, Date startDate) + { + return subject + " (initiated at " + startDate + ")"; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java index 97ddf4e4a61ca353fe79c05efa80391e58c097e8..227092708f6d6fb80bea6b0ed05e9d4b24f834bd 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java @@ -2486,5 +2486,4 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt return UserFailureException.fromTemplate(exception, "%s '%s': %s", entity.getEntityKind() .getDescription(), entity.getIdentifier(), exception.getMessage()); } - } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/IASyncAction.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/IASyncAction.java new file mode 100644 index 0000000000000000000000000000000000000000..cdeb8bde40c84f114ec6ebc4c9e112fa33feff75 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/IASyncAction.java @@ -0,0 +1,29 @@ +/* + * Copyright 2011 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.server; + +import java.io.Writer; + +/** + * @author Pawel Glyzewski + */ +public interface IASyncAction +{ + public boolean doAction(Writer messageWriter); + + public String getName(); +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java index df5c19a4bdc3dca9d16910423e433d813223b6f9..bdc6e4191ea327a684d7e0666feea10b0c1a9ff9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java @@ -47,6 +47,8 @@ public final class ResourceNames public final static String ENTITY_INFORMATION_PROVIDER = "entity-information-provider"; + public static final String MAIL_CLIENT_PARAMETERS = "mail-client-parameters"; + private ResourceNames() { // Can not be instantiated. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java index 5c9215db4546d71c350c9e568531949fbeeac836..1ebf3c689b8848ab83a6dc0845d3ef18c2555996 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java @@ -178,7 +178,7 @@ public interface IGenericClientService extends IClientService * Updates samples and materials from excel files which have been previously uploaded. */ public List<BatchRegistrationResult> registerOrUpdateSamplesAndMaterials( - final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting) - throws UserFailureException; + final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting, + boolean async, String userEmail) throws UserFailureException; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java index 667c16a8d64bcd60e3d281f00eb9acbf7eb1913a..de524f2dc8f71bcdcc254496a33a2233fcc7d0c3 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java @@ -151,10 +151,12 @@ public interface IGenericClientServiceAsync extends IClientServiceAsync AsyncCallback<List<BatchRegistrationResult>> registerExperimentsCallback); /** - * @see IGenericClientService#registerOrUpdateSamplesAndMaterials(String, String, boolean) + * @see IGenericClientService#registerOrUpdateSamplesAndMaterials(String, String, boolean, + * boolean, String) */ public void registerOrUpdateSamplesAndMaterials(final String sessionKey, - final String defaultGroupIdentifier, boolean updateExisting, + final String defaultGroupIdentifier, boolean updateExisting, boolean async, + String userEmail, AsyncCallback<List<BatchRegistrationResult>> registerSamplesAndMaterialsCallback) throws UserFailureException; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java index fcd6cd75f10c2431e53274cf486879b0782b37f7..05f548c86797ed93e1d397d805d55e0ec3bbbda0 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java @@ -39,6 +39,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.ICl import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.IModule; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractViewer; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GeneralImportComponent; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.LinkExtractor; import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithPermId; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdAndCodeHolder; @@ -98,6 +99,26 @@ public final class ClientPluginFactory extends AbstractClientPluginFactory<Gener public final <T extends BasicEntityType, I extends IIdAndCodeHolder> IClientPlugin<T, I> createClientPlugin( EntityKind entityKind) { + if (entityKind == null) + { + return new ClientPluginAdapter<T, I>() + { + @Override + public Widget createBatchRegistrationForEntityType(final T entityType) + { + return createBatchUpdateForEntityType(entityType); + } + + @Override + public Widget createBatchUpdateForEntityType(T entityType) + { + return new GeneralImportForm(getViewContext(), + GeneralImportComponent.createId(), + GeneralImportComponent.SESSION_KEY); + } + + }; + } if (EntityKind.EXPERIMENT.equals(entityKind)) { return (IClientPlugin<T, I>) new ExperimentClientPlugin(); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java new file mode 100644 index 0000000000000000000000000000000000000000..a9e984d0adb347ab3580d365bc946e026fc1eb5d --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java @@ -0,0 +1,213 @@ +package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application; + +import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware; + +import java.util.List; + +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.Listener; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.form.CheckBox; +import com.extjs.gxt.ui.client.widget.form.Field; +import com.extjs.gxt.ui.client.widget.form.FileUploadField; +import com.extjs.gxt.ui.client.widget.form.TextField; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.AbstractImagePrototype; + +import ch.systemsx.cisd.openbis.generic.client.web.client.application.FormPanelListener; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.file.BasicFileFieldManager; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchRegistrationResult; +import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; + +public class GeneralImportForm extends AbstractRegistrationForm +{ + protected final class RegisterOrUpdateSamplesAndMaterialsCallback extends + AbstractRegistrationForm.AbstractRegistrationCallback<List<BatchRegistrationResult>> + { + RegisterOrUpdateSamplesAndMaterialsCallback( + final IViewContext<IGenericClientServiceAsync> viewContext) + { + super(viewContext); + } + + @Override + protected String createSuccessfullRegistrationInfo( + final List<BatchRegistrationResult> result) + { + final StringBuilder builder = new StringBuilder(); + for (final BatchRegistrationResult batchRegistrationResult : result) + { + builder.append("<b>" + batchRegistrationResult.getFileName() + "</b>: "); + builder.append(batchRegistrationResult.getMessage()); + builder.append("<br />"); + } + return builder.toString(); + } + } + + private static final String FIELD_LABEL_TEMPLATE = "File"; + + private static final int NUMBER_OF_FIELDS = 1; + + private final String sessionKey; + + private final BasicFileFieldManager fileFieldsManager; + + private final TextField<String> emailField; + + private final CheckBox asynchronous; + + private final IViewContext<IGenericClientServiceAsync> genericViewContext; + + /** + * @param genericViewContext + * @param id + */ + public GeneralImportForm(IViewContext<IGenericClientServiceAsync> genericViewContext, + String id, String sessionKey) + { + super(genericViewContext, id); + + this.sessionKey = sessionKey; + this.genericViewContext = genericViewContext; + setScrollMode(Scroll.AUTO); + asynchronous = createCheckBox(); + emailField = + createEmailField(genericViewContext.getModel().getSessionContext().getUser() + .getUserEmail()); + fileFieldsManager = + new BasicFileFieldManager(sessionKey, NUMBER_OF_FIELDS, FIELD_LABEL_TEMPLATE); + fileFieldsManager.setMandatory(); + addUploadFeatures(sessionKey); + } + + @Override + protected final void onRender(final Element target, final int index) + { + System.out.println("onRender!"); + super.onRender(target, index); + addFormFields(false); + } + + private CheckBox createCheckBox() + { + final CheckBox checkBox = new CheckBox(); + checkBox.setFieldLabel("Asynchronous?"); + checkBox.setBoxLabel(""); + checkBox.setValue(true); + checkBox.addListener(Events.Change, new Listener<BaseEvent>() + { + public void handleEvent(BaseEvent be) + { + System.out.println("Event!"); + if (checkBox.getValue()) + { + formPanel.removeAll(); + addFormFields(true); + } else + { + formPanel.remove(emailField); + } + formPanel.layout(); + } + }); + return checkBox; + } + + private TextField<String> createEmailField(String userEmail) + { + TextField<String> field = new TextField<String>(); + field.setAllowBlank(false); + field.setFieldLabel("Email"); + FieldUtil.markAsMandatory(field); + field.setValue(userEmail); + field.setValidateOnBlur(true); + field.setRegex(GenericConstants.EMAIL_REGEX); + field.getMessages().setRegexText("Expected email address format: user@domain.com"); + AbstractImagePrototype infoIcon = + AbstractImagePrototype.create(genericViewContext.getImageBundle().getInfoIcon()); + FieldUtil.addInfoIcon(field, + "All relevant notifications will be send to this email address", + infoIcon.createImage()); + return field; + } + + @Override + protected void submitValidForm() + { + } + + @Override + protected void resetFieldsAfterSave() + { + for (FileUploadField attachmentField : fileFieldsManager.getFields()) + { + attachmentField.reset(); + } + } + + private final void addFormFields(boolean forceAddEmailField) + { + formPanel.add(asynchronous); + if (forceAddEmailField || asynchronous.getValue()) + { + formPanel.add(emailField); + } + for (FileUploadField attachmentField : fileFieldsManager.getFields()) + { + formPanel.add(wrapUnaware((Field<?>) attachmentField).get()); + } + formPanel.addListener(Events.Submit, new FormPanelListener(infoBox) + { + @Override + protected void onSuccessfullUpload() + { + save(); + } + + @Override + protected void setUploadEnabled() + { + GeneralImportForm.this.setUploadEnabled(true); + } + }); + redefineSaveListeners(); + } + + void redefineSaveListeners() + { + saveButton.removeAllListeners(); + saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() + { + @Override + public final void componentSelected(final ButtonEvent ce) + { + if (formPanel.isValid()) + { + if (fileFieldsManager.filesDefined() > 0) + { + setUploadEnabled(false); + formPanel.submit(); + } else + { + save(); + } + } + } + }); + } + + protected void save() + { + genericViewContext.getService().registerOrUpdateSamplesAndMaterials(sessionKey, null, true, + asynchronous.getValue(), emailField.getValue(), + new RegisterOrUpdateSamplesAndMaterialsCallback(genericViewContext)); + } +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java index fd80dc542a2200e9508fda1b513e3293c06eb9d0..2517a8f801f4214197ac50f6ea532b2acee5edfe 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java @@ -173,8 +173,8 @@ public class GenericClientService extends AbstractClientService implements IGene } public final List<BatchRegistrationResult> registerOrUpdateSamplesAndMaterials( - final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting) - throws UserFailureException + final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting, + boolean async, String userEmail) throws UserFailureException { BatchOperationKind operationKind = updateExisting ? BatchOperationKind.UPDATE : BatchOperationKind.REGISTRATION; @@ -197,13 +197,27 @@ public class GenericClientService extends AbstractClientService implements IGene parseMaterials(session, uploadedFiles, materialType, "MATERIALS", updateExisting); final String sessionToken = getSessionToken(); - genericServer.registerOrUpdateSamplesAndMaterials(sessionToken, - samplesInfo.getSamples(), materialsInfo.getMaterials()); - List<BatchRegistrationResult> results = new ArrayList<BatchRegistrationResult>(); - results.addAll(materialsInfo.getResultList()); - results.addAll(samplesInfo.getResultList()); - return results; + if (async) + { + genericServer.registerOrUpdateSamplesAndMaterialsAsync(sessionToken, + samplesInfo.getSamples(), materialsInfo.getMaterials(), userEmail); + + List<BatchRegistrationResult> results = new ArrayList<BatchRegistrationResult>(); + results.add(new BatchRegistrationResult(uploadedFiles.iterable().iterator().next() + .getOriginalFilename(), "File will be processed asynchronously.")); + + return results; + } else + { + genericServer.registerOrUpdateSamplesAndMaterials(sessionToken, + samplesInfo.getSamples(), materialsInfo.getMaterials()); + + List<BatchRegistrationResult> results = new ArrayList<BatchRegistrationResult>(); + results.addAll(materialsInfo.getResultList()); + results.addAll(samplesInfo.getResultList()); + return results; + } } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e) { throw UserFailureExceptionTranslator.translate(e); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java index df37d8bb7b707f10dc84f3ce392fb6fdbc449c5c..dafb53f7661730c3cb7b884af189052af5c2590f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java @@ -16,6 +16,7 @@ package ch.systemsx.cisd.openbis.plugin.generic.server; +import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -33,6 +34,7 @@ import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; import ch.systemsx.cisd.openbis.generic.server.AbstractServer; +import ch.systemsx.cisd.openbis.generic.server.IASyncAction; import ch.systemsx.cisd.openbis.generic.server.MaterialHelper; import ch.systemsx.cisd.openbis.generic.server.batch.BatchOperationExecutor; import ch.systemsx.cisd.openbis.generic.server.batch.IBatchOperation; @@ -114,6 +116,9 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER) protected ICommonServer commonServer; + @Resource(name = ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames.GENERIC_PLUGIN_SERVER) + private IGenericServer genericServer; + public GenericServer() { } @@ -779,9 +784,31 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen public void registerOrUpdateSamplesAndMaterials(final String sessionToken, final List<NewSamplesWithTypes> newSamplesWithType, - List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException + final List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException { registerOrUpdateMaterials(sessionToken, newMaterialsWithType); registerOrUpdateSamples(sessionToken, newSamplesWithType); } + + public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken, + final List<NewSamplesWithTypes> newSamplesWithType, + final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail) + throws UserFailureException + { + executeASync(userEmail, new IASyncAction() + { + public String getName() + { + return "General Import"; + } + + public boolean doAction(Writer messageWriter) + { + genericServer.registerOrUpdateSamplesAndMaterials(sessionToken, + newSamplesWithType, newMaterialsWithType); + return true; + } + }); + } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java index 9c1a2f1d88e26e2dde4e17bbcd70b252e0107ee9..46ea258776fee4e9ac1eacbbfbc3c0c9771fc61b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java @@ -107,31 +107,13 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric public void registerMaterials(String sessionToken, List<NewMaterialsWithTypes> newMaterials) { - StringBuilder sb = new StringBuilder(); - for (NewMaterialsWithTypes s : newMaterials) - { - if (sb.length() > 0) - { - sb.append(","); - } - sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); - } - logTracking(sessionToken, "register_materials", sb.toString()); + logTracking(sessionToken, "register_materials", getMaterials(newMaterials)); } public int updateMaterials(String sessionToken, List<NewMaterialsWithTypes> newMaterials, boolean ignoreUnregisteredMaterials) throws UserFailureException { - StringBuilder sb = new StringBuilder(); - for (NewMaterialsWithTypes s : newMaterials) - { - if (sb.length() > 0) - { - sb.append(","); - } - sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); - } - logTracking(sessionToken, "update_materials", sb.toString()); + logTracking(sessionToken, "update_materials", getMaterials(newMaterials)); return 0; } @@ -202,31 +184,13 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric public void registerSamples(String sessionToken, List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException { - StringBuilder sb = new StringBuilder(); - for (NewSamplesWithTypes s : newSamplesWithType) - { - if (sb.length() > 0) - { - sb.append(","); - } - sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); - } - logTracking(sessionToken, "register_samples", sb.toString()); + logTracking(sessionToken, "register_samples", getSamples(newSamplesWithType)); } public void updateSamples(String sessionToken, List<NewSamplesWithTypes> updatedSamplesWithType) throws UserFailureException { - StringBuilder sb = new StringBuilder(); - for (NewSamplesWithTypes s : updatedSamplesWithType) - { - if (sb.length() > 0) - { - sb.append(","); - } - sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); - } - logTracking(sessionToken, "update_samples", sb.toString()); + logTracking(sessionToken, "update_samples", getSamples(updatedSamplesWithType)); } public void registerOrUpdateMaterials(String sessionToken, List<NewMaterialsWithTypes> materials) @@ -242,16 +206,7 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric public void registerOrUpdateSamples(String sessionToken, List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException { - StringBuilder sb = new StringBuilder(); - for (NewSamplesWithTypes s : newSamplesWithType) - { - if (sb.length() > 0) - { - sb.append(","); - } - sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); - } - logTracking(sessionToken, "register_or_update_samples", sb.toString()); + logTracking(sessionToken, "register_or_update_samples", getSamples(newSamplesWithType)); } public void updateDataSets(String sessionToken, NewDataSetsWithTypes dataSets) @@ -277,7 +232,25 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric public void registerOrUpdateSamplesAndMaterials(final String sessionToken, final List<NewSamplesWithTypes> newSamplesWithType, - List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException + final List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException + { + + logTracking(sessionToken, "register_or_update_samples_and_materials", + "SAMPLES(%s) MATERIALS(%s)", getSamples(newSamplesWithType), + getMaterials(newMaterialsWithType)); + } + + public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken, + final List<NewSamplesWithTypes> newSamplesWithType, + final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail) + throws UserFailureException + { + logTracking(sessionToken, "register_or_update_samples_and_materials_async", + "SAMPLES(%s) MATERIALS(%s) EMAIL(%s)", getSamples(newSamplesWithType), + getMaterials(newMaterialsWithType), userEmail); + } + + private static String getSamples(final List<NewSamplesWithTypes> newSamplesWithType) { StringBuilder samples = new StringBuilder(); for (NewSamplesWithTypes s : newSamplesWithType) @@ -289,6 +262,11 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric samples.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); } + return samples.toString(); + } + + private static String getMaterials(final List<NewMaterialsWithTypes> newMaterialsWithType) + { StringBuilder materials = new StringBuilder(); for (NewMaterialsWithTypes s : newMaterialsWithType) { @@ -298,7 +276,7 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric } materials.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size()); } - logTracking(sessionToken, "register_or_update_samples_and_materials", - "SAMPLES(%s) MATERIALS(%s)", samples.toString(), materials.toString()); + + return materials.toString(); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java index 7507775d932599857f3da6a517e52d68dcf62b3f..367e42198ebd0d6b06446a0a632465eafe9d2006 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java @@ -150,6 +150,18 @@ public interface IGenericServer extends IServer final List<NewSamplesWithTypes> newSamplesWithType, List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException; + /** + * Asynchronously registers or updates samples and materials of different types in batches. + */ + @Transactional + @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN) + @DatabaseCreateOrDeleteModification(value = + { ObjectKind.SAMPLE, ObjectKind.MATERIAL }) + public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken, + final List<NewSamplesWithTypes> newSamplesWithType, + final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail) + throws UserFailureException; + /** * Updates samples of different types in batches. */ 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 63e8b045cc0894d632ea920b32a967fb2ef79429..204366730d2a06930e1174e1c8d3405054477d23 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 @@ -448,7 +448,9 @@ var common = { ARCHIVING_MENU_UNARCHIVE: "Unarchive", ARCHIVING_MENU_LOCK: "Disable", ARCHIVING_MENU_UNLOCK: "Enable", - + + GENERAL_IMPORT_MENU: "General Import", + menu_modules: "Utilities", // @@ -475,7 +477,7 @@ var common = { list_groups: "Spaces Browser", confirm_title: "Confirmation", confirm_close_msg: "All unsaved changes will be lost. Are you sure?", - + general_import: "General Import", // // Help Page Titles diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml index 672df3f473020d91bcc96c1f985924d7011a1a47..2a68174d1627c700e55ea1488114ed3e6d669774 100644 --- a/openbis/source/java/genericApplicationContext.xml +++ b/openbis/source/java/genericApplicationContext.xml @@ -221,6 +221,18 @@ <bean class="ch.systemsx.cisd.common.spring.LogAdvisor" /> <bean class="ch.systemsx.cisd.common.spring.MarkerLogApplicationListener"/> + + <!-- + //Mail Client Parameters + --> + <bean id="mail-client-parameters" class="ch.systemsx.cisd.common.mail.MailClientParameters"> + <property name="from" value="${mail.from}"/> + <property name="smtpHost" value="${mail.smtp.host}"/> + <property name="smtpUser" value="${mail.smtp.user}"/> + <property name="smtpPassword" value="${mail.smtp.password}"/> + </bean> + + <!-- // Plugins --> @@ -231,5 +243,4 @@ <plugins:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </plugins:component-scan> - </beans> \ No newline at end of file diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected index 7507775d932599857f3da6a517e52d68dcf62b3f..367e42198ebd0d6b06446a0a632465eafe9d2006 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected @@ -150,6 +150,18 @@ public interface IGenericServer extends IServer final List<NewSamplesWithTypes> newSamplesWithType, List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException; + /** + * Asynchronously registers or updates samples and materials of different types in batches. + */ + @Transactional + @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN) + @DatabaseCreateOrDeleteModification(value = + { ObjectKind.SAMPLE, ObjectKind.MATERIAL }) + public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken, + final List<NewSamplesWithTypes> newSamplesWithType, + final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail) + throws UserFailureException; + /** * Updates samples of different types in batches. */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java index bdd80dece9a79b70f929df1bad74035cceebdd34..37640f70b8107dfab62fec758214addf968f9c40 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java @@ -37,7 +37,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync; import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ExperimentAnalysisSummarySection; import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ExperimentWellMaterialsSection; -import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.LibraryImportComponent; import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.WellSearchComponent; import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.locator.GlobalWellSearchLocatorResolver; @@ -63,9 +62,7 @@ public class ScreeningModule implements IModule ActionMenu globalWellSearch = TabActionMenuItemFactory .createActionMenu(viewContext, ID, createGlobalWellSearch()); - ActionMenu globalLibraryImport = - TabActionMenuItemFactory.createActionMenu(viewContext, ID, createLibraryImport()); - return Arrays.asList(globalWellSearch, globalLibraryImport); + return Arrays.asList(globalWellSearch); } private ITabActionMenuItemDefinition<IScreeningClientServiceAsync> createGlobalWellSearch() @@ -98,35 +95,6 @@ public class ScreeningModule implements IModule }; } - private ITabActionMenuItemDefinition<IScreeningClientServiceAsync> createLibraryImport() - { - return new ITabActionMenuItemDefinition<IScreeningClientServiceAsync>() - { - - public String getName() - { - return Dict.LIBRARY_IMPORT_MENU_ITEM; - } - - public String getHelpPageTitle() - { - return "Global Library Import"; - } - - public String tryGetLink() - { - return null; - } - - public DatabaseModificationAwareComponent createComponent( - @SuppressWarnings("hiding") IViewContext<IScreeningClientServiceAsync> viewContext) - { - TabContent libraryImportTab = new LibraryImportComponent(viewContext); - return DatabaseModificationAwareComponent.wrapUnaware(libraryImportTab); - } - }; - } - public String getName() { return viewContext.getMessage(Dict.SCREENING_MODULE_TITLE); diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LibraryImportComponent.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LibraryImportComponent.java deleted file mode 100644 index cc7cf5a40878f9bed3d8f5aad762229ca2dde617..0000000000000000000000000000000000000000 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LibraryImportComponent.java +++ /dev/null @@ -1,199 +0,0 @@ -package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers; - -import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware; - -import java.util.List; - -import com.extjs.gxt.ui.client.Style.Scroll; -import com.extjs.gxt.ui.client.event.ButtonEvent; -import com.extjs.gxt.ui.client.event.Events; -import com.extjs.gxt.ui.client.event.SelectionListener; -import com.extjs.gxt.ui.client.widget.form.Field; -import com.extjs.gxt.ui.client.widget.form.FileUploadField; -import com.google.gwt.user.client.Element; - -import ch.systemsx.cisd.openbis.generic.client.web.client.application.FormPanelListener; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.file.BasicFileFieldManager; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchRegistrationResult; -import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; -import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.GenericViewContext; -import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync; -import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict; -import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningModule; -import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria.ExperimentSearchCriteria; - -/** - * Allows to specify search criteria for materials contained in wells. Used in experiment section - * panel or as a standalone module. - * - * @author Tomasz Pylak - */ -public class LibraryImportComponent extends TabContent -{ - - private static class LibraryImportForm extends AbstractRegistrationForm - { - protected final class RegisterOrUpdateSamplesAndMaterialsCallback - extends - AbstractRegistrationForm.AbstractRegistrationCallback<List<BatchRegistrationResult>> - { - RegisterOrUpdateSamplesAndMaterialsCallback( - final IViewContext<IGenericClientServiceAsync> viewContext) - { - super(viewContext); - } - - @Override - protected String createSuccessfullRegistrationInfo( - final List<BatchRegistrationResult> result) - { - final StringBuilder builder = new StringBuilder(); - for (final BatchRegistrationResult batchRegistrationResult : result) - { - builder.append("<b>" + batchRegistrationResult.getFileName() + "</b>: "); - builder.append(batchRegistrationResult.getMessage()); - builder.append("<br />"); - } - return builder.toString(); - } - } - - private static final String PREFIX = "library-import"; - - private static final String SESSION_KEY = PREFIX; - - private static final String FIELD_LABEL_TEMPLATE = "File"; - - private static final int NUMBER_OF_FIELDS = 1; - - private final BasicFileFieldManager fileFieldsManager; - - private final IViewContext<IGenericClientServiceAsync> genericViewContext; - - private static String createId(String sessionKey) - { - return ScreeningModule.ID + sessionKey; - } - - /** - * @param viewContext - */ - protected LibraryImportForm(IViewContext<IGenericClientServiceAsync> viewContext) - { - super(viewContext, createId(SESSION_KEY)); - - this.genericViewContext = viewContext; - setScrollMode(Scroll.AUTO); - fileFieldsManager = - new BasicFileFieldManager(SESSION_KEY, NUMBER_OF_FIELDS, FIELD_LABEL_TEMPLATE); - fileFieldsManager.setMandatory(); - addUploadFeatures(SESSION_KEY); - } - - @Override - protected final void onRender(final Element target, final int index) - { - super.onRender(target, index); - addFormFields(); - } - - @Override - protected void submitValidForm() - { - } - - @Override - protected void resetFieldsAfterSave() - { - for (FileUploadField attachmentField : fileFieldsManager.getFields()) - { - attachmentField.reset(); - } - } - - private final void addFormFields() - { - for (FileUploadField attachmentField : fileFieldsManager.getFields()) - { - formPanel.add(wrapUnaware((Field<?>) attachmentField).get()); - } - formPanel.addListener(Events.Submit, new FormPanelListener(infoBox) - { - @Override - protected void onSuccessfullUpload() - { - save(); - } - - @Override - protected void setUploadEnabled() - { - LibraryImportForm.this.setUploadEnabled(true); - } - }); - redefineSaveListeners(); - } - - void redefineSaveListeners() - { - saveButton.removeAllListeners(); - saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() - { - @Override - public final void componentSelected(final ButtonEvent ce) - { - if (formPanel.isValid()) - { - if (fileFieldsManager.filesDefined() > 0) - { - setUploadEnabled(false); - formPanel.submit(); - } else - { - save(); - } - } - } - }); - } - - protected void save() - { - genericViewContext.getService().registerOrUpdateSamplesAndMaterials(SESSION_KEY, null, - true, new RegisterOrUpdateSamplesAndMaterialsCallback(genericViewContext)); - } - } - - private final IViewContext<IGenericClientServiceAsync> genericViewContext; - - public static String getTabTitle(IViewContext<IScreeningClientServiceAsync> viewContext) - { - return viewContext.getMessage(Dict.LIBRARY_IMPORT_TAB_TITLE); - } - - public LibraryImportComponent(IViewContext<IScreeningClientServiceAsync> screeningViewContext) - { - this(screeningViewContext, ExperimentSearchCriteria.createAllExperiments()); - - setContentVisible(true); - } - - public LibraryImportComponent(IViewContext<IScreeningClientServiceAsync> screeningViewContext, - ExperimentSearchCriteria experimentSearchCriteria) - { - super(getTabTitle(screeningViewContext), screeningViewContext, null); - this.genericViewContext = - new GenericViewContext(screeningViewContext.getCommonViewContext()); - } - - @Override - protected void showContent() - { - removeAll(); - add(new LibraryImportForm(genericViewContext)); - layout(); - } -} \ No newline at end of file diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java index 687ce99d83d7ac6dbfd3e17da7e0654da94797e0..6f765573fdb9e8dff0023f8cfb4e0f435d9deb10 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java @@ -1,13 +1,15 @@ package ch.systemsx.cisd.openbis.plugin.screening.server; +import java.io.IOException; +import java.io.Writer; import java.util.Arrays; -import java.util.Date; import java.util.List; import ch.rinn.restrictions.Private; +import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; import ch.systemsx.cisd.common.collections.TableMap; -import ch.systemsx.cisd.common.mail.IMailClient; import ch.systemsx.cisd.common.shared.basic.utils.StringUtils; +import ch.systemsx.cisd.openbis.generic.server.IASyncAction; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.util.KeyExtractorFactory; import ch.systemsx.cisd.openbis.generic.shared.ICommonServer; @@ -30,21 +32,13 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConst * * @author Izabela Adamczyk */ -class LibraryRegistrationTask implements Runnable +class LibraryRegistrationTask implements IASyncAction { - private static final String SUCCESSFUL_LIBRARY_REGISTARION_STATUS = - "Library successfully registered"; - - private static final String UNSUCCESSFUL_LIBRARY_REGISTARION_STATUS = - "Library registration failed"; - private static final String DELIM = " "; private final String sessionToken; - private final String email; - private final List<NewMaterial> newGenesOrNull; private final List<NewMaterial> newOligosOrNull; @@ -57,45 +51,20 @@ class LibraryRegistrationTask implements Runnable private final IDAOFactory daoFactory; - private final IMailClient mailClient; - - public LibraryRegistrationTask(String sessionToken, String email, - List<NewMaterial> newGenesOrNull, List<NewMaterial> newOligosOrNull, - List<NewSamplesWithTypes> newSamplesWithType, ICommonServer commonServer, - IGenericServer server, IDAOFactory daoFactory, IMailClient mailClient) + public LibraryRegistrationTask(String sessionToken, List<NewMaterial> newGenesOrNull, + List<NewMaterial> newOligosOrNull, List<NewSamplesWithTypes> newSamplesWithType, + ICommonServer commonServer, IGenericServer server, IDAOFactory daoFactory) { this.sessionToken = sessionToken; - this.email = email; this.newGenesOrNull = newGenesOrNull; this.newOligosOrNull = newOligosOrNull; this.newSamplesWithType = newSamplesWithType; this.commonServer = commonServer; this.genericServer = server; this.daoFactory = daoFactory; - this.mailClient = mailClient; } - public void run() - { - boolean success = true; - Date startDate = new Date(); - StringBuilder message = new StringBuilder(); - - try - { - // when one of these methods fails it will throw an unchecked exception - registerOrUpdateGenes(message); - registerOrUpdateOligos(message); - registerOrUpdateSamples(message); - } catch (RuntimeException rex) - { - success = false; - } - - sendEmail(message.toString(), startDate, email, success); - } - - private void registerOrUpdateSamples(StringBuilder message) + private void registerOrUpdateSamples(Writer message) throws IOException { try { @@ -104,14 +73,14 @@ class LibraryRegistrationTask implements Runnable genericServer.registerOrUpdateSamples(sessionToken, newSamplesWithType); for (NewSamplesWithTypes s : newSamplesWithType) { - message.append("Successfuly saved " + s.getNewEntities().size() + message.write("Successfuly saved " + s.getNewEntities().size() + " samples of type " + s.getEntityType() + ".\n"); } } } catch (RuntimeException ex) { - message.append("ERROR: Plates and wells could not be saved!\n"); - message.append(ex.getMessage()); + message.write("ERROR: Plates and wells could not be saved!\n"); + message.write(ex.getMessage()); throw ex; } } @@ -136,7 +105,7 @@ class LibraryRegistrationTask implements Runnable return materialsWithTypes; } - private void registerOrUpdateOligos(StringBuilder message) + private void registerOrUpdateOligos(Writer message) throws IOException { try { @@ -144,17 +113,17 @@ class LibraryRegistrationTask implements Runnable { registerOrUpdateMaterials(ScreeningConstants.SIRNA_PLUGIN_TYPE_NAME, newOligosOrNull); - message.append("Successfuly saved " + newOligosOrNull.size() + " siRNAs.\n"); + message.write("Successfuly saved " + newOligosOrNull.size() + " siRNAs.\n"); } } catch (RuntimeException ex) { - message.append("ERROR: siRNAs could not be saved!\n"); - message.append(ex.getMessage()); + message.write("ERROR: siRNAs could not be saved!\n"); + message.write(ex.getMessage()); throw ex; } } - private void registerOrUpdateGenes(StringBuilder message) + private void registerOrUpdateGenes(Writer message) throws IOException { try { @@ -171,13 +140,13 @@ class LibraryRegistrationTask implements Runnable } registerOrUpdateMaterials(ScreeningConstants.GENE_PLUGIN_TYPE_CODE, newGenesOrNull); - message.append("Successfuly saved properties of " + newGenesOrNull.size() + message.write("Successfuly saved properties of " + newGenesOrNull.size() + " genes.\n"); } } catch (RuntimeException ex) { - message.append("ERROR: Genes could not be saved!\n"); - message.append(ex.getMessage()); + message.write("ERROR: Genes could not be saved!\n"); + message.write(ex.getMessage()); throw ex; } } @@ -247,19 +216,24 @@ class LibraryRegistrationTask implements Runnable } } - private void sendEmail(String content, Date startDate, String recipient, boolean successful) + public boolean doAction(Writer messageWriter) { - String status = - successful ? SUCCESSFUL_LIBRARY_REGISTARION_STATUS - : UNSUCCESSFUL_LIBRARY_REGISTARION_STATUS; + try + { + registerOrUpdateGenes(messageWriter); + registerOrUpdateOligos(messageWriter); + registerOrUpdateSamples(messageWriter); - String subject = addDate(status, startDate); - mailClient.sendMessage(subject, content, null, null, recipient); + return true; + } catch (IOException ex) + { + throw new IOExceptionUnchecked(ex); + } } - private static String addDate(String subject, Date startDate) + public String getName() { - return subject + " (initiated at " + startDate + ")"; + return "Library registration"; } } \ No newline at end of file diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java index 958ddbff4d91baf0fffde16006e855791f9d41af..24596df1974e710424b315b3e2d3bfff6581af1f 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java @@ -20,9 +20,6 @@ import java.sql.Connection; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import javax.annotation.Resource; @@ -34,9 +31,6 @@ import org.springframework.stereotype.Component; import ch.rinn.restrictions.Private; import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.common.mail.IMailClient; -import ch.systemsx.cisd.common.mail.MailClient; -import ch.systemsx.cisd.common.mail.MailClientParameters; import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; import ch.systemsx.cisd.openbis.generic.server.AbstractServer; import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager; @@ -132,21 +126,16 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl */ public static final int MINOR_VERSION = 7; - private static ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 10, 360, - TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); - @Resource(name = ResourceNames.SCREENING_BUSINESS_OBJECT_FACTORY) private IScreeningBusinessObjectFactory businessObjectFactory; @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER) private ICommonServer commonServer; + // necessary to make it possible to run asynchronous actions @Resource(name = ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames.GENERIC_PLUGIN_SERVER) private IGenericServer genericServer; - @Resource(name = ResourceNames.MAIL_CLIENT_PARAMETERS) - private MailClientParameters mailClientParameters; - public ScreeningServer() { } @@ -287,10 +276,8 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl List<NewMaterial> newGenesOrNull, List<NewMaterial> newOligosOrNull, List<NewSamplesWithTypes> newSamplesWithType) { - IMailClient mailClient = new MailClient(mailClientParameters); - executor.submit(new LibraryRegistrationTask(sessionToken, userEmail, newGenesOrNull, - newOligosOrNull, newSamplesWithType, commonServer, genericServer, getDAOFactory(), - mailClient)); + executeASync(userEmail, new LibraryRegistrationTask(sessionToken, newGenesOrNull, + newOligosOrNull, newSamplesWithType, commonServer, genericServer, getDAOFactory())); } public List<Material> listExperimentMaterials(String sessionToken, TechId experimentId, diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java index cba01cf953cd84f0a8a859b60ffd4159388ba05f..3cb3884ff6afb6d7c13804871fa22c745f920dc1 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java @@ -42,6 +42,4 @@ public final class ResourceNames public final static String SCREENING_DAO_FACTORY = "screening-dao-factory"; public final static String SCREENING_SAMPLE_SERVER_PLUGIN = "screening-sample-server-plugin"; - - public static final String MAIL_CLIENT_PARAMETERS = "mail-client-parameters"; } diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java index 149b6f297d4108cd118ceeab771e708cec9b1f9c..03d4609f20a4edacf29658dfba28750deb6a6314 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java @@ -16,8 +16,7 @@ package ch.systemsx.cisd.openbis.plugin.screening.server; -import static org.hamcrest.text.StringContains.containsString; - +import java.io.StringWriter; import java.util.Arrays; import java.util.List; @@ -29,8 +28,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import ch.rinn.restrictions.Friend; -import ch.systemsx.cisd.common.mail.From; -import ch.systemsx.cisd.common.mail.IMailClient; import ch.systemsx.cisd.common.test.RecordingMatcher; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO; @@ -59,8 +56,6 @@ public class LibraryRegistrationTaskTest extends AssertJUnit { private static final String SESSION_TOKEN = "session"; - private static final String USER_EMAIL = "micky.mouse@acme.org"; - private Mockery context; private ICommonServer commonServer; @@ -71,8 +66,6 @@ public class LibraryRegistrationTaskTest extends AssertJUnit private IEntityTypeDAO entityTypeDAO; - private IMailClient mailClient; - private LibraryRegistrationTask task; @BeforeMethod @@ -83,7 +76,6 @@ public class LibraryRegistrationTaskTest extends AssertJUnit genericServer = context.mock(IGenericServer.class); daoFactory = context.mock(IDAOFactory.class); entityTypeDAO = context.mock(IEntityTypeDAO.class); - mailClient = context.mock(IMailClient.class); } @AfterMethod @@ -110,8 +102,8 @@ public class LibraryRegistrationTaskTest extends AssertJUnit new RecordingMatcher<List<NewMaterialsWithTypes>>(); task = - new LibraryRegistrationTask(SESSION_TOKEN, USER_EMAIL, newGenes, null, null, - commonServer, genericServer, daoFactory, mailClient); + new LibraryRegistrationTask(SESSION_TOKEN, newGenes, null, null, commonServer, + genericServer, daoFactory); context.checking(new Expectations() { @@ -129,16 +121,10 @@ public class LibraryRegistrationTaskTest extends AssertJUnit one(genericServer).registerOrUpdateMaterials(with(SESSION_TOKEN), with(materialsWithTypesMatcher)); - - String[] emailTo = new String[] - { USER_EMAIL }; - one(mailClient).sendMessage(with(containsString("success")), - with(any(String.class)), with(aNull(String.class)), - with(aNull(From.class)), with(emailTo)); } }); - task.run(); + task.doAction(new StringWriter()); assertEquals("ABC A AB", extractGeneSymbol(g1)); assertEquals("AB", extractGeneSymbol(g2));