/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2014, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.webui; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.vaadin.addon.jpacontainer.JPAContainer; import com.vaadin.addon.jpacontainer.provider.LocalEntityProvider; import com.vaadin.addon.jpacontainer.util.DefaultQueryModifierDelegate; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.terminal.ThemeResource; import com.vaadin.ui.Button; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.TabSheet; import com.vaadin.ui.TextArea; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.themes.BaseTheme; import org.activiti.engine.ActivitiException; import org.activiti.engine.ProcessEngine; import org.activiti.engine.impl.ServiceImpl; import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.interceptor.CommandExecutor; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.tepi.filtertable.FilterTable; import ru.codeinside.adm.database.Employee; import ru.codeinside.adm.database.Group; import ru.codeinside.adm.database.Role; import ru.codeinside.adm.database.SmevTask; import ru.codeinside.adm.ui.BooleanColumnGenerator; import ru.codeinside.adm.ui.DateColumnGenerator; import ru.codeinside.adm.ui.FilterDecorator_; import ru.codeinside.adm.ui.FilterGenerator_; import ru.codeinside.gses.activiti.behavior.SmevTaskBehavior; import ru.codeinside.gses.service.Fn; import ru.codeinside.gses.webui.supervisor.DiagramPanel; import ru.codeinside.jpa.ActivitiEntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; import java.util.HashSet; import java.util.List; import java.util.Set; final public class SmevTasksPanel extends VerticalLayout implements TabSheet.SelectedTabChangeListener { final FilterTable table; Set<Role> roles = Flash.flash().getRoles(); final ErrorBlock errorBlock = new ErrorBlock(); public SmevTasksPanel() { setSizeFull(); setMargin(true); setSpacing(true); final JPAContainer<SmevTask> container = new JPAContainer<SmevTask>(SmevTask.class); container.setEntityProvider(new LocalEntityProvider<SmevTask>(SmevTask.class, ActivitiEntityManager.INSTANCE)); if (!roles.contains(Role.SuperSupervisor)) { container.setQueryModifierDelegate(new DefaultQueryModifierDelegate() { @Override public void filtersWillBeAdded(CriteriaBuilder criteriaBuilder, CriteriaQuery<?> query, List<Predicate> predicates) { // полный доступ для общего управляющего if (roles.contains(Role.SuperSupervisor)) { return; } String login = Flash.login(); Set<String> groupNames = getGroupNames(login); Root<?> smevTask = query.getRoots().iterator().next(); Path<String> path = smevTask.get("employee").get("login"); Predicate loginPredicate = criteriaBuilder.equal(path, login); if (!groupNames.isEmpty()) { Subquery groups = query.subquery(Long.class); Root sameTask = groups.from(SmevTask.class); groups.select(sameTask.get("id")); groups.where(criteriaBuilder.and( criteriaBuilder.equal(sameTask.get("id"), smevTask.get("id")), sameTask.get("groups").in(groupNames) )); predicates.add(criteriaBuilder.or(loginPredicate, criteriaBuilder.exists(groups))); } else { predicates.add(loginPredicate); } } private Set<String> getGroupNames(String login) { Set<String> groupNames = new HashSet<String>(); Employee currentEmployee = ActivitiEntityManager.INSTANCE.find(Employee.class, login); if (roles.contains(Role.Supervisor)) { for (Group group : currentEmployee.getEmployeeGroups()) { groupNames.add(group.getName()); } for (Group group : currentEmployee.getOrganizationGroups()) { groupNames.add(group.getName()); } } if (roles.contains(Role.Declarant) || roles.contains(Role.Executor)) { for (Group group : currentEmployee.getGroups()) { groupNames.add(group.getName()); } } return groupNames; } }); } container.addNestedContainerProperty("employee.login"); container.addNestedContainerProperty("bid.id"); table = new FilterTable(); table.setFilterBarVisible(true); table.setFilterDecorator(new FilterDecorator_()); table.setFilterGenerator(new FilterGenerator_(ImmutableList.of( "id", "bid.id", "revision", "pingCount", "errorCount"), ImmutableList.of( "needUserReaction", "responseType", "requestType"))); table.setContainerDataSource(container); table.setDescription("Процессы на этапе вызова СМЭВ"); table.setSizeFull(); table.setVisibleColumns(new String[]{ "bid.id", "consumer", "revision", "requestType", "responseType", "employee.login", "needUserReaction", "lastChange", "pingCount", "errorCount" }); table.setColumnHeaders(new String[]{ "Заявка", "Потребитель", "Ревизия", "Отправлено", "Получено", "Заявитель", "Требует внимания", "Последнее изменение", "К-во опросов", "К-во ошибок" }); table.addGeneratedColumn("lastChange", new DateColumnGenerator("dd.MM.yyyy HH:mm:ss")); table.addGeneratedColumn("needUserReaction", new BooleanColumnGenerator()); table.setSelectable(true); table.setNullSelectionAllowed(true); table.setImmediate(true); table.addListener(new SmevTaskClickListener()); table.setCellStyleGenerator(new SmevStylist(table)); addComponent(table); setExpandRatio(table, 1f); addComponent(errorBlock); setExpandRatio(errorBlock, 0.7f); } final private class SmevTaskClickListener implements Property.ValueChangeListener { @Override public void valueChange(Property.ValueChangeEvent event) { final FilterTable table = (FilterTable) event.getProperty(); final Object index = table.getValue(); Long smevTaskId = null; if (index != null) { final Item item = table.getItem(index); smevTaskId = Fn.getValue(item, "id", Long.class); } if (smevTaskId != null) { final SmevTask smevTask = ActivitiEntityManager.INSTANCE.find(SmevTask.class, smevTaskId); errorBlock.setTask(smevTask); } else { errorBlock.setTask(null); } } } private class UserActionListener implements Button.ClickListener { boolean repeat; UserActionListener(boolean repeat) { this.repeat = repeat; } @Override public void buttonClick(Button.ClickEvent event) { final Object index = table.getValue(); Long smevTaskId = null; Integer revision = null; if (index != null) { final Item item = table.getItem(index); smevTaskId = Fn.getValue(item, "id", Long.class); revision = Fn.getValue(item, "revision", Integer.class); } if (smevTaskId != null) { SmevTask current = ActivitiEntityManager.INSTANCE.find(SmevTask.class, smevTaskId); if (current.getRevision() == revision) { executeActivity(current, repeat); getWindow().showNotification( repeat ? "Исполнение возобновлено" : "Исполнение прервано", Window.Notification.TYPE_HUMANIZED_MESSAGE); } else { getWindow().showNotification("Действие уже произошло!"); } refresh(); } } void executeActivity(final SmevTask smevTask, final boolean repeat) { Flash.flash().getActivitiService().withEngine(new Function<ProcessEngine, Object>() { @Override public Object apply(ProcessEngine engine) { CommandExecutor commandExecutor = ((ServiceImpl) engine.getTaskService()).getCommandExecutor(); return commandExecutor.execute( new Command<Object>() { @Override public Object execute(CommandContext commandContext) { ExecutionEntity execution = commandContext.getExecutionManager().findExecutionById(smevTask.getExecutionId()); ActivityImpl activity = execution.getProcessDefinition().findActivity(smevTask.getTaskId()); try { ((SmevTaskBehavior) activity.getActivityBehavior()).doUserAction(execution, repeat); } catch (Exception e) { throw new ActivitiException("user reaction fail", e); } return null; } } ); } }); } } final class ErrorBlock extends HorizontalLayout { final TextArea textArea = new TextArea("Последняя ошибка:"); final VerticalLayout diagramLayout = new VerticalLayout(); final Button refresh = new Button("Обновить"); final Button restart = new Button("Возобновить"); final Button end = new Button("Прервать"); ErrorBlock() { setSizeFull(); setSpacing(true); textArea.setSizeFull(); textArea.setStyleName("small"); diagramLayout.setCaption("Маршрут исполнения заявки:"); diagramLayout.setSizeFull(); VerticalLayout buttons = new VerticalLayout(); buttons.setSizeUndefined(); buttons.setMargin(false); buttons.setSpacing(true); buttons.addComponent(refresh); buttons.addComponent(new Label(" ")); buttons.addComponent(new Label(" ")); buttons.addComponent(restart); buttons.addComponent(end); addComponent(buttons); addComponent(diagramLayout); addComponent(textArea); setExpandRatio(diagramLayout, 0.42f); setExpandRatio(textArea, 0.42f); setTask(null); refresh.setStyleName(BaseTheme.BUTTON_LINK); refresh.setDescription("Обновить таблицу СМЭВ"); refresh.setIcon(new ThemeResource("../runo/icons/32/reload.png")); refresh.addListener(new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { refresh(); getWindow().showNotification("Таблица обновлена", Window.Notification.TYPE_HUMANIZED_MESSAGE); } }); restart.setStyleName(BaseTheme.BUTTON_LINK); restart.setDescription("Возобновить процесс"); restart.setIcon(new ThemeResource("../runo/icons/32/ok.png")); restart.addListener(new UserActionListener(true)); end.setStyleName(BaseTheme.BUTTON_LINK); end.setDescription("Остановить процесс"); end.setIcon(new ThemeResource("../runo/icons/32/cancel.png")); end.addListener(new UserActionListener(false)); } public void setTask(final SmevTask smevTask) { boolean enabled = smevTask != null; if (!enabled) { textArea.setVisible(false); } else { String failure = smevTask.getFailure(); if (failure == null) { textArea.setVisible(false); } else { textArea.setVisible(true); textArea.setReadOnly(false); textArea.setValue(failure); textArea.setReadOnly(true); } } boolean actionEnabled = enabled && smevTask.isNeedUserReaction(); restart.setEnabled(actionEnabled); restart.setVisible(actionEnabled); end.setEnabled(actionEnabled); end.setVisible(actionEnabled); diagramLayout.setVisible(enabled); diagramLayout.removeAllComponents(); if (enabled) { diagramLayout.addComponent( new DiagramPanel(smevTask.getBid().getProcedureProcessDefinition().getProcessDefinitionId(), smevTask.getExecutionId()) ); } } } @Override public void selectedTabChange(TabSheet.SelectedTabChangeEvent event) { if (this != event.getTabSheet().getSelectedTab()) { return; } refresh(); } void refresh() { Object oldValue = table.getValue(); table.setValue(null); table.removeAllItems(); table.refreshRowCache(); if (oldValue != null) { table.setValue(oldValue); } else { errorBlock.setTask(null); } } }