package com.constellio.app.modules.rm.extensions;
import com.constellio.app.api.extensions.PagesComponentsExtension;
import com.constellio.app.api.extensions.params.DecorateMainComponentAfterInitExtensionParams;
import com.constellio.app.modules.rm.RMConfigs;
import com.constellio.app.modules.rm.constants.RMPermissionsTo;
import com.constellio.app.modules.rm.model.enums.FolderStatus;
import com.constellio.app.modules.rm.services.RMSchemasRecordsServices;
import com.constellio.app.modules.rm.services.borrowingServices.BorrowingServices;
import com.constellio.app.modules.rm.services.decommissioning.DecommissioningService;
import com.constellio.app.modules.rm.ui.pages.containers.DisplayContainerViewImpl;
import com.constellio.app.modules.rm.ui.pages.folder.DisplayFolderViewImpl;
import com.constellio.app.modules.rm.wrappers.ContainerRecord;
import com.constellio.app.modules.rm.wrappers.Folder;
import com.constellio.app.modules.tasks.model.wrappers.Task;
import com.constellio.app.modules.tasks.model.wrappers.request.BorrowRequest;
import com.constellio.app.modules.tasks.model.wrappers.request.ExtensionRequest;
import com.constellio.app.modules.tasks.model.wrappers.request.ReactivationRequest;
import com.constellio.app.modules.tasks.model.wrappers.request.ReturnRequest;
import com.constellio.app.modules.tasks.services.TasksSchemasRecordsServices;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.app.ui.framework.buttons.BaseButton;
import com.constellio.app.ui.framework.buttons.ConfirmDialogButton;
import com.constellio.app.ui.framework.buttons.WindowButton;
import com.constellio.app.ui.framework.components.BaseForm;
import com.constellio.app.ui.framework.components.fields.number.BaseIntegerField;
import com.constellio.app.ui.framework.decorators.base.ActionMenuButtonsDecorator;
import com.constellio.app.ui.pages.base.BasePresenterUtils;
import com.constellio.app.ui.pages.base.BaseView;
import com.constellio.app.ui.pages.base.BaseViewImpl;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.frameworks.validation.ValidationException;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.model.services.records.RecordServicesException;
import com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators;
import com.vaadin.data.fieldgroup.PropertyId;
import com.vaadin.ui.*;
import com.vaadin.ui.themes.ValoTheme;
import org.joda.time.LocalDate;
import org.vaadin.dialogs.ConfirmDialog;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static com.constellio.app.ui.i18n.i18n.$;
/**
* Created by Constellio on 2017-03-16.
*/
public class RMRequestTaskButtonExtension extends PagesComponentsExtension {
enum RequestType {
EXTENSION, BORROW, REACTIVATION
}
String collection;
AppLayerFactory appLayerFactory;
ModelLayerFactory modelLayerFactory;
TasksSchemasRecordsServices taskSchemas;
RMSchemasRecordsServices rmSchemas;
BorrowingServices borrowingServices;
DecommissioningService decommissioningService;
public RMRequestTaskButtonExtension(String collection, AppLayerFactory appLayerFactory) {
this.collection = collection;
this.appLayerFactory = appLayerFactory;
this.modelLayerFactory = appLayerFactory.getModelLayerFactory();
this.taskSchemas = new TasksSchemasRecordsServices(collection, appLayerFactory);
this.rmSchemas = new RMSchemasRecordsServices(collection, appLayerFactory);
this.borrowingServices = new BorrowingServices(collection, modelLayerFactory);
this.decommissioningService = new DecommissioningService(collection, appLayerFactory);
}
@Override
public void decorateMainComponentAfterViewAssembledOnViewEntered(DecorateMainComponentAfterInitExtensionParams params) {
super.decorateMainComponentAfterViewAssembledOnViewEntered(params);
Component mainComponent = params.getMainComponent();
Folder folder;
ContainerRecord container;
User currentUser;
if (mainComponent instanceof DisplayFolderViewImpl) {
DisplayFolderViewImpl view = (DisplayFolderViewImpl) mainComponent;
folder = rmSchemas.getFolder(view.getRecord().getId());
if(folder.getContainer() != null) {
container = rmSchemas.getContainerRecord(folder.getContainer());
} else {
container = null;
}
currentUser = getCurrentUser(view);
adjustButtons(view, folder, container, currentUser);
} else if (mainComponent instanceof DisplayContainerViewImpl) {
DisplayContainerViewImpl view = (DisplayContainerViewImpl) mainComponent;
folder = null;
container = rmSchemas.getContainerRecord(view.getPresenter().getContainerId());
currentUser = getCurrentUser(view);
adjustButtons(view, folder, container, currentUser);
}
}
public void adjustButtons(BaseViewImpl view, Folder folder, ContainerRecord containerRecord, User currentUser) {
List<Button> actionMenuButtons = view.getActionMenuButtons();
for(Button button: actionMenuButtons) {
if (button.getId() != null) {
switch (button.getId()) {
case BorrowRequest.SCHEMA_NAME:
button.setVisible(isPrincipalRecordBorrowable(folder, containerRecord, currentUser));
break;
case ReturnRequest.SCHEMA_NAME:
button.setVisible(isPrincipalRecordReturnable(folder, containerRecord, currentUser));
break;
case ReactivationRequest.SCHEMA_NAME:
button.setVisible(isPrincipalRecordReativable(folder, containerRecord, currentUser));
break;
case ExtensionRequest.SCHEMA_NAME:
button.setVisible(isPrincipalRecordReturnable(folder, containerRecord, currentUser));
break;
}
}
}
}
private boolean isPrincipalRecordReativable(Folder folder, ContainerRecord containerRecord, User currentUser) {
if(folder != null) {
return isFolderReactivable(folder, currentUser);
} else {
return isContainerReactivable(containerRecord, currentUser);
}
}
private boolean isContainerReactivable(ContainerRecord containerRecord, User currentUser) {
List<Folder> folders = rmSchemas.searchFolders(LogicalSearchQueryOperators.from(rmSchemas.folder.schemaType()).where(rmSchemas.folder.container()).isEqualTo(containerRecord.getId()));
if(folders != null) {
for(Folder folder: folders) {
if(isFolderReactivable(folder, currentUser)) {
return true;
}
}
}
return false;
}
private boolean isFolderBorrowable(Folder folder, ContainerRecord container, User currentUser) {
if(folder != null) {
try {
this.borrowingServices.validateCanBorrow(currentUser, folder, LocalDate.now());
} catch (Exception e) {
return false;
}
}
return folder != null && currentUser.hasAll(RMPermissionsTo.BORROW_FOLDER, RMPermissionsTo.BORROWING_REQUEST_ON_FOLDER).on(folder)
&& !(container != null && Boolean.TRUE.equals(container.getBorrowed()));
}
private boolean isContainerBorrowable(ContainerRecord container, User currentUser) {
if(container != null) {
try {
this.borrowingServices.validateCanBorrow(currentUser, container, LocalDate.now());
} catch (Exception e) {
return false;
}
}
return container != null && currentUser.hasAll(RMPermissionsTo.BORROW_CONTAINER, RMPermissionsTo.BORROWING_REQUEST_ON_CONTAINER).on(container);
}
private boolean isPrincipalRecordBorrowable(Folder folder, ContainerRecord container, User currentUser) {
if(folder != null) {
return isFolderBorrowable(folder, container, currentUser);
} else {
return isContainerBorrowable(container, currentUser);
}
}
private boolean isPrincipalRecordReturnable(Folder folder, ContainerRecord container, User currentUser) {
if(folder != null) {
return folder != null && Boolean.TRUE.equals(folder.getBorrowed()) && currentUser.getId().equals(folder.getBorrowUser());
} else {
return container != null && Boolean.TRUE.equals(container.getBorrowed()) && currentUser.getId().equals(container.getBorrower());
}
}
private boolean isFolderReactivable(Folder folder, User currentUser) {
return decommissioningService.isFolderReactivable(folder, currentUser);
}
@Override
public void decorateMainComponentBeforeViewInstanciated(DecorateMainComponentAfterInitExtensionParams params) {
}
@Override
public void decorateMainComponentBeforeViewAssembledOnViewEntered(DecorateMainComponentAfterInitExtensionParams params) {
super.decorateMainComponentAfterViewAssembledOnViewEntered(params);
Component mainComponent = params.getMainComponent();
if (mainComponent instanceof DisplayFolderViewImpl || mainComponent instanceof DisplayContainerViewImpl) {
BaseViewImpl view = (BaseViewImpl) mainComponent;
view.addActionMenuButtonsDecorator(new ActionMenuButtonsDecorator() {
@Override
public void decorate(final BaseViewImpl view, List<Button> actionMenuButtons) {
Context context = buildContext(view);
Folder folder = context.getFolder();
if(folder.getArchivisticStatus() != FolderStatus.INACTIVE_DESTROYED)
{
actionMenuButtons.add(buildRequestBorrowButton(view));
actionMenuButtons.add(buildRequestBorrowExtensionButton(view));
actionMenuButtons.add(buildRequestReactivationButton(view));
}
actionMenuButtons.add(buildRequestReturnButton(view));
}
});
}
}
private User getCurrentUser(BaseView view) {
BasePresenterUtils basePresenterUtils = new BasePresenterUtils(view.getConstellioFactories(), view.getSessionContext());
return basePresenterUtils.getCurrentUser();
}
private Button buildRequestBorrowButton(final BaseViewImpl view) {
WindowButton borrowRequestButton = new WindowButton($("RMRequestTaskButtonExtension.borrowRequest"), $("RMRequestTaskButtonExtension.requestBorrowButtonTitle")) {
@Override
protected Component buildWindowContent() {
getWindow().setHeight("250px");
final Context context = buildContext(view);
final Folder folder = context.getFolder();
final ContainerRecord container = context.getContainer();
final User currentUser = context.getCurrentUser();
VerticalLayout mainLayout = new VerticalLayout();
final BaseIntegerField borrowDurationField = new BaseIntegerField($("RMRequestTaskButtonExtension.borrowDuration"));
borrowDurationField.setValue(String.valueOf(new RMConfigs(modelLayerFactory.getSystemConfigurationsManager()).getBorrowingDurationDays()));
HorizontalLayout buttonLayout = new HorizontalLayout();
BaseButton borrowFolderButton = new BaseButton($("RMRequestTaskButtonExtension.confirmBorrowFolder")) {
@Override
protected void buttonClick(ClickEvent event) {
borrowRequest(view, false, borrowDurationField.getValue());
getWindow().close();
}
@Override
public boolean isVisible() {
return isFolderBorrowable(folder, container, currentUser);
}
};
borrowFolderButton.setStyleName(ValoTheme.BUTTON_PRIMARY);
BaseButton borrowContainerButton = new BaseButton($("RMRequestTaskButtonExtension.confirmBorrowContainer")) {
@Override
protected void buttonClick(ClickEvent event) {
borrowRequest(view, true, borrowDurationField.getValue());
getWindow().close();
}
@Override
public boolean isVisible() {
return isContainerBorrowable(container, currentUser);
}
};
borrowContainerButton.setStyleName(ValoTheme.BUTTON_PRIMARY);
BaseButton cancelButton = new BaseButton($("cancel")) {
@Override
protected void buttonClick(ClickEvent event) {
getWindow().close();
}
};
TextArea messageField = new TextArea();
messageField.setHeight("50%");
messageField.setWidth("100%");
messageField.addStyleName(ValoTheme.TEXTAREA_BORDERLESS);
if(borrowFolderButton.isVisible() && borrowContainerButton.isVisible()) {
messageField.setValue($("RMRequestTaskButtonExtension.requestBorrowFolderOrContainerMessage"));
} else if(borrowFolderButton.isVisible()) {
messageField.setValue($("RMRequestTaskButtonExtension.requestBorrowFolderMessage"));
} else {
messageField.setValue($("RMRequestTaskButtonExtension.requestBorrowContainerMessage"));
}
messageField.setReadOnly(true);
buttonLayout.setSpacing(true);
buttonLayout.addComponents(borrowContainerButton, borrowFolderButton, cancelButton);
mainLayout.setHeight("100%");
mainLayout.setWidth("100%");
mainLayout.setSpacing(true);
mainLayout.addComponents(messageField, borrowDurationField, buttonLayout);
return mainLayout;
}
};
borrowRequestButton.setId(BorrowRequest.SCHEMA_NAME);
return borrowRequestButton;
}
private Button buildRequestReturnButton(final BaseViewImpl view) {
ConfirmDialogButton returnRequestButton = new ConfirmDialogButton($("RMRequestTaskButtonExtension.returnRequest")) {
@Override
protected String getConfirmDialogMessage() {
return $("DisplayFolderView.confirmReturnMessage");
}
@Override
protected void confirmButtonClick(ConfirmDialog dialog) {
returnRequest(view);
}
};
returnRequestButton.setId(ReturnRequest.SCHEMA_NAME);
return returnRequestButton;
}
private Button buildRequestReactivationButton(final BaseViewImpl view) {
WindowButton reactivationRequestButton = new WindowButton($("RMRequestTaskButtonExtension.reactivationRequest"), $("RMRequestTaskButtonExtension.reactivationRequest")) {
@PropertyId("value")
private InlineDateField datefield;
@Override
protected Component buildWindowContent() {
Label dateLabel = new Label($("DisplayFolderView.confirmReactivationMessage"));
datefield = new InlineDateField();
List<BaseForm.FieldAndPropertyId> fields = Collections.singletonList(new BaseForm.FieldAndPropertyId(datefield, "value"));
Request req = new Request(new Date(), RequestType.REACTIVATION);
BaseForm form = new BaseForm<Request>(req, this, datefield) {
@Override
protected void saveButtonClick(Request viewObject) throws ValidationException {
viewObject.setValue(datefield.getValue());
reactivationRequested(view, viewObject);
getWindow().close();
}
@Override
protected void cancelButtonClick(Request viewObject) {
getWindow().close();
}
};
return form;
}
public void setDatefield(InlineDateField datefield) {
this.datefield = datefield;
}
public InlineDateField getDatefield() {
return this.datefield;
}
};
reactivationRequestButton.setId(ReactivationRequest.SCHEMA_NAME);
return reactivationRequestButton;
}
private Button buildRequestBorrowExtensionButton(final BaseViewImpl view) {
WindowButton borrowExtensionRequestButton = new WindowButton($("RMRequestTaskButtonExtension.borrowExtensionRequest"), $("RMRequestTaskButtonExtension.borrowExtensionRequestTitle")) {
@PropertyId("value")
private InlineDateField datefield;
@Override
protected Component buildWindowContent() {
Label dateLabel = new Label($("DisplayFolderView.chooseDateToExtends"));
datefield = new InlineDateField();
List<BaseForm.FieldAndPropertyId> fields = Collections.singletonList(new BaseForm.FieldAndPropertyId(datefield, "value"));
Request req = new Request(new Date(), RequestType.EXTENSION);
BaseForm form = new BaseForm<Request>(req, this, datefield) {
@Override
protected void saveButtonClick(Request viewObject) throws ValidationException {
viewObject.setValue(datefield.getValue());
borrowExtensionRequested(view, viewObject);
getWindow().close();
}
@Override
protected void cancelButtonClick(Request viewObject) {
getWindow().close();
}
};
return form;
}
public void setDatefield(InlineDateField datefield) {
this.datefield = datefield;
}
public InlineDateField getDatefield() {
return this.datefield;
}
};
borrowExtensionRequestButton.setId(ExtensionRequest.SCHEMA_NAME);
return borrowExtensionRequestButton;
}
public void borrowRequest(BaseViewImpl view, boolean isContainer, String inputForNumberOfDays) {
Context context = buildContext(view);
Folder folder = context.getFolder();
ContainerRecord container = context.getContainer();
User currentUser = context.getCurrentUser();
int numberOfDays = 1;
if(inputForNumberOfDays != null && inputForNumberOfDays.matches("^-?\\d+$")) {
numberOfDays = Integer.parseInt(inputForNumberOfDays);
if(numberOfDays <= 0) {
view.showErrorMessage($("RMRequestTaskButtonExtension.invalidBorrowDuration"));
return;
}
} else {
view.showErrorMessage($("RMRequestTaskButtonExtension.invalidBorrowDuration"));
return;
}
try {
Task borrowRequest;
if(isContainer) {
String recordId = container.getId();
borrowRequest = taskSchemas.newBorrowContainerRequestTask(currentUser.getId(), getAssignees(recordId), recordId, numberOfDays, container.getTitle());
} else {
String recordId = folder.getId();
borrowRequest = taskSchemas.newBorrowFolderRequestTask(currentUser.getId(), getAssignees(recordId), recordId, numberOfDays, folder.getTitle());
}
modelLayerFactory.newRecordServices().add(borrowRequest);
view.showMessage($("RMRequestTaskButtonExtension.borrowSuccess"));
} catch (RecordServicesException e) {
e.printStackTrace();
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
}
public void returnRequest(BaseViewImpl view) {
Context context = buildContext(view);
Folder folder = context.getFolder();
ContainerRecord container = context.getContainer();
User currentUser = context.getCurrentUser();
try {
if(folder != null) {
String folderId = folder.getId();
Task returnRequest = taskSchemas.newReturnFolderRequestTask(currentUser.getId(), getAssignees(folderId), folderId, folder.getTitle());
modelLayerFactory.newRecordServices().add(returnRequest);
} else if (container != null) {
String containerId = container.getId();
Task returnRequest = taskSchemas.newReturnContainerRequestTask(currentUser.getId(), getAssignees(containerId), containerId, container.getTitle());
modelLayerFactory.newRecordServices().add(returnRequest);
} else {
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
view.showMessage($("RMRequestTaskButtonExtension.returnSuccess"));
} catch (RecordServicesException e) {
e.printStackTrace();
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
}
public void reactivationRequested(BaseViewImpl view, Request req) {
Context context = buildContext(view);
Folder folder = context.getFolder();
ContainerRecord container = context.getContainer();
User currentUser = context.getCurrentUser();
LocalDate localDate = new LocalDate(req.getValue());
try {
if(folder != null) {
String folderId = folder.getId();
Task reactivationRequest = taskSchemas.newReactivateFolderRequestTask(currentUser.getId(), getAssignees(folderId), folderId, folder.getTitle(), localDate);
modelLayerFactory.newRecordServices().add(reactivationRequest);
} else if (container != null) {
String containerId = container.getId();
Task reactivationRequest = taskSchemas.newReactivationContainerRequestTask(currentUser.getId(), getAssignees(containerId), containerId, container.getTitle(), localDate);
modelLayerFactory.newRecordServices().add(reactivationRequest);
} else {
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
view.showMessage($("RMRequestTaskButtonExtension.reactivationSuccess"));
} catch (RecordServicesException e) {
e.printStackTrace();
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
}
public void borrowExtensionRequested(BaseViewImpl view, Request req) {
Context context = buildContext(view);
Folder folder = context.getFolder();
ContainerRecord container = context.getContainer();
User currentUser = context.getCurrentUser();
try {
if(folder != null) {
String folderId = folder.getId();
Task borrowExtensionRequest = taskSchemas.newBorrowFolderExtensionRequestTask(currentUser.getId(), getAssignees(folderId), folderId, folder.getTitle(), new LocalDate(req.getValue()));
modelLayerFactory.newRecordServices().add(borrowExtensionRequest);
} else if (container != null) {
String containerId = container.getId();
Task borrowExtensionRequest = taskSchemas.newBorrowContainerExtensionRequestTask(currentUser.getId(), getAssignees(containerId), containerId, container.getTitle(), new LocalDate(req.getValue()));
modelLayerFactory.newRecordServices().add(borrowExtensionRequest);
} else {
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
view.showMessage($("RMRequestTaskButtonExtension.borrowExtensionSuccess"));
} catch (RecordServicesException e) {
e.printStackTrace();
view.showErrorMessage($("RMRequestTaskButtonExtension.errorWhileCreatingTask"));
}
}
private List<String> getAssignees(String recordId) {
return modelLayerFactory.newAuthorizationsServices()
.getUserIdsWithPermissionOnRecord(RMPermissionsTo.MANAGE_REQUEST_ON_FOLDER, modelLayerFactory.newRecordServices().getDocumentById(recordId));
}
static public class Request {
@PropertyId("value")
public Object value;
@PropertyId("type")
public RequestType type;
public Request() {
}
public Request(Object value, RequestType requestType) {
this.type = requestType;
this.value = value;
}
public Object getValue() {
return value;
}
public Request setValue(Object value) {
this.value = value;
return this;
}
public RequestType getType() {
return type;
}
public Request setType(RequestType type) {
this.type = type;
return this;
}
}
public class Context {
Folder folder;
ContainerRecord container;
User currentUser;
public Context(Folder folder, ContainerRecord container, User currentUser) {
this.folder = folder;
this.container = container;
this.currentUser = currentUser;
}
public Folder getFolder() {
return folder;
}
public ContainerRecord getContainer() {
return container;
}
public User getCurrentUser() {
return currentUser;
}
}
public Context buildContext(BaseViewImpl baseView) {
Folder folder;
ContainerRecord container;
User currentUser;
if (baseView instanceof DisplayFolderViewImpl) {
DisplayFolderViewImpl view = (DisplayFolderViewImpl) baseView;
folder = rmSchemas.getFolder(view.getRecord().getId());
if(folder.getContainer() != null) {
container = rmSchemas.getContainerRecord(folder.getContainer());
} else {
container = null;
}
currentUser = getCurrentUser(view);
} else if (baseView instanceof DisplayContainerViewImpl) {
DisplayContainerViewImpl view = (DisplayContainerViewImpl) baseView;
folder = null;
container = rmSchemas.getContainerRecord(view.getPresenter().getContainerId());
currentUser = getCurrentUser(view);
} else {
return null;
}
return new Context(folder, container, currentUser);
}
}