CCM NG: WorkflowAdminPane ported

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4253 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-09-03 15:21:28 +00:00
parent 72b017faee
commit ed824be970
10 changed files with 809 additions and 170 deletions

View File

@ -27,7 +27,7 @@ import com.arsdigita.bebop.form.OptionGroup;
import java.util.List;
/**
* Migrated from the {@code DataQueryPrintListener} in the old system. Renamed
* Migrated from the {@code DataQueryOptionPrintListener} in the old system. Renamed
* and refactored to operate on a list.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>

View File

@ -1,120 +0,0 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* The contents of this file are subject to the CCM Public
* License (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.redhat.com/licenses/ccmpl.html.
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language
* governing rights and limitations under the License.
*
*/
package com.arsdigita.cms.ui.workflow;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.TableModel;
import org.librecms.workflow.CmsTask;
import org.librecms.workflow.CmsTaskType;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.Assert;
import com.arsdigita.web.Web;
import org.apache.logging.log4j.LogManager;
import org.libreccm.workflow.Workflow;
import java.util.Collections;
import java.util.Iterator;
import org.apache.logging.log4j.Logger;
/**
*
*
*/
class AssignedTaskTableModelBuilder extends AbstractTableModelBuilder {
private final WorkflowRequestLocal m_workflow;
public AssignedTaskTableModelBuilder(final WorkflowRequestLocal workflow) {
m_workflow = workflow;
}
@Override
public TableModel makeModel(final Table table, final PageState state) {
return new Model(m_workflow.getWorkflow(state));
}
private static class Model implements TableModel {
private final Iterator m_iter;
private CmsTask m_task;
Model(final Workflow workflow) {
Assert.exists(workflow, Workflow.class);
if (workflow.getProcessState() == Workflow.STARTED) {
final Engine engine = Engine.getInstance(CMSEngine.CMS_ENGINE_TYPE);
Assert.exists(engine, Engine.class);
m_iter = engine.getEnabledTasks(Web.getWebContext().getUser(), workflow.getID()).iterator();
} else {
m_iter = Collections.emptyList().iterator();
}
}
@Override
public final int getColumnCount() {
return 3;
}
@Override
public final boolean nextRow() {
if (m_iter.hasNext()) {
m_task = (CmsTask) m_iter.next();
return true;
} else {
return false;
}
}
public final Object getKeyAt(final int column) {
return m_task.getID();
}
public final Object getElementAt(final int column) {
switch (column) {
case 0:
return m_task.getLabel();
case 1:
// SF patch [ 1587168 ] Show locking user
return m_task.isLocked() ? m_task.getLockedUser() : null;
case 2:
return m_task.getTaskType().getID().equals(CmsTaskType.DEPLOY)
? (Object) new Label("") : // null should work as well
(Object) lz("cms.ui.workflow.task.finish");
default:
throw new IllegalStateException();
}
}
}
protected final static GlobalizedMessage gz(final String key) {
return GlobalizationUtil.globalize(key);
}
protected final static String lz(final String key) {
return (String) gz(key).localize();
}
}

View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* The contents of this file are subject to the CCM Public
* License (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.redhat.com/licenses/ccmpl.html.
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language
* governing rights and limitations under the License.
*
*/
package com.arsdigita.cms.ui.workflow;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormValidationListener;
import com.arsdigita.bebop.form.CheckboxGroup;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.TextArea;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.IntegerParameter;
import com.arsdigita.cms.ui.BaseForm;
import com.arsdigita.cms.ui.ListOptionPrintListener;
import org.librecms.workflow.CmsTaskType;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.KernelConfig;
import org.apache.logging.log4j.LogManager;
import org.libreccm.workflow.Task;
import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.workflow.TaskRepository;
import org.libreccm.workflow.WorkflowManager;
import org.librecms.CmsConstants;
import org.librecms.workflow.CmsTaskTypeRepository;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TooManyListenersException;
/**
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @author <a href="jross@redhat.com">Justin Ross</a>
*/
class BaseTaskForm extends BaseForm {
private static final Logger LOGGER = LogManager
.getLogger(BaseTaskForm.class);
final WorkflowRequestLocal m_workflow;
final TextField m_name;
final TextArea m_description;
final OptionGroup m_type;
final OptionGroup m_deps;
BaseTaskForm(final String key,
final GlobalizedMessage message,
final WorkflowRequestLocal workflow) {
super(key, message);
m_workflow = workflow;
m_name = new Name("name", 200, true);
addField(gz("cms.ui.name"), m_name);
m_type = new SingleSelect(new IntegerParameter("task_type"));
addField(gz("cms.ui.workflow.task.type"), m_type);
try {
m_type.addPrintListener(new TaskTypePrintListener());
} catch (TooManyListenersException ex) {
throw new RuntimeException(ex);
}
m_description = new Description("desc", 4000, true);
addField(gz("cms.ui.description"), m_description);
m_deps = new CheckboxGroup("dep");
addField(gz("cms.ui.workflow.task.dependencies"), m_deps);
addAction(new Finish());
addAction(new Cancel());
addSecurityListener(CmsConstants.PRIVILEGE_ADMINISTER_WORKFLOW);
addValidationListener(new ValidationListener());
}
private class ValidationListener implements FormValidationListener {
@Override
public final void validate(final FormSectionEvent e)
throws FormProcessException {
final String name = (String) m_name.getValue(e.getPageState());
// XXX do a dupe check here ala commented out code below
}
}
/*
protected void addValidationListener() {
addValidationListener(new DataQueryExistsListener(ERROR_MSG) {
private final String QUERY_NAME =
"com.arsdigita.workflow.simple.getTasks";
public void validate(FormSectionEvent event)
throws FormProcessException {
String name = (String) m_name.getValue(event.getPageState());
if ( name != null ) {
super.validate(event);
} else {
// Do nothing. Let the NotNullValidationListener fire.
}
}
public DataQuery getDataQuery(FormSectionEvent e) {
PageState s = e.getPageState();
Session session = SessionManager.getSession();
DataQuery query = session.retrieveQuery(QUERY_NAME);
Filter f = query.addFilter("lower(taskLabel) = lower(:label)");
f.set("label", ((String) m_name.getValue(s)).trim());
Filter parentFilter = query.addFilter("taskParentId = :parent_id");
parentFilter.set("parent_id", m_processes.getSelectedKey(s));
Filter itemFilter = query.addNotEqualsFilter
("taskId", (BigDecimal)m_id.getValue(s));
return query;
}
});
}
*/
// Fix this one too
private class TaskTypePrintListener extends ListOptionPrintListener<CmsTaskType> {
@Override
protected List<CmsTaskType> getDataQuery(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CmsTaskTypeRepository taskTypeRepo = cdiUtil.findBean(
CmsTaskTypeRepository.class);
final List<CmsTaskType> taskTypes = taskTypeRepo.findAll();
return taskTypes;
}
@Override
public String getKey(final CmsTaskType taskType) {
return Long.toString(taskType.getTaskTypeId());
}
@Override
public String getValue(final CmsTaskType taskType) {
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Locale defaultLocale = kernelConfig.getDefaultLocale();
return taskType.getName().getValue(defaultLocale);
}
}
/**
* This method decides which dependencies have to be removed and which ones
* newly added. Unfortunately we cannot just do "remove all", and add the
* new ones in since it is possible that Tasks will fire events when
* dependencies are added and removed.
*
*/
final void processDependencies(final Task task,
final String[] selectedDependencies) {
final List<Task> dependencies = task.getDependentTasks();
final Map<Long, Task> toAdd = new HashMap<>();
final Map<Long, Task> toRemove = new HashMap<>();
// Everything is to be removed unless it is in the array.
dependencies.forEach(temp -> toRemove.put(temp.getTaskId(), temp));
final CdiUtil cdiUtil =CdiUtil.createCdiUtil();
final TaskRepository taskRepo = cdiUtil.findBean(TaskRepository.class);
final WorkflowManager workflowManager = cdiUtil.findBean(WorkflowManager.class);
Long selectedId;
Object addedTask;
if (selectedDependencies != null) {
for (String selectedDependency : selectedDependencies) {
selectedId = Long.parseLong(selectedDependency);
addedTask = toRemove.remove(selectedId);
if (addedTask == null) {
toAdd.put(selectedId, taskRepo.findById(selectedId));
}
}
}
toRemove.values().forEach(temp -> workflowManager.removeDependentTask(
task, temp));
toAdd.values().forEach(temp -> workflowManager.addDependentTask(task,
temp));
}
}

View File

@ -32,16 +32,29 @@ import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.cms.ui.BaseDeleteForm;
import com.arsdigita.cms.ui.BaseItemPane;
import com.arsdigita.cms.ui.VisibilityComponent;
import com.arsdigita.kernel.KernelConfig;
import org.librecms.workflow.CmsTask;
import org.libreccm.security.User;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.PropertyList;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.Web;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.Shiro;
import org.libreccm.workflow.Task;
import org.libreccm.workflow.TaskRepository;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowManager;
import org.librecms.CmsConstants;
import org.librecms.workflow.CmsTaskTypeRepository;
import java.math.BigDecimal;
import java.util.List;
import java.util.Locale;
abstract class BaseWorkflowItemPane extends BaseItemPane {
@ -66,24 +79,23 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
m_detailPane = new SimpleContainer();
// Tasks
final FinishLink taskFinishLink = new FinishLink();
final ActionLink taskAddLink = new ActionLink
(new Label(gz("cms.ui.workflow.task.add")));
final TaskAddForm taskAddForm = new TaskAddForm
(m_workflow, m_tasks.getRowSelectionModel());
final ActionLink taskAddLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.add")));
final TaskAddForm taskAddForm = new TaskAddForm(m_workflow, m_tasks
.getRowSelectionModel());
final ActionLink taskEditLink = new ActionLink
(new Label(gz("cms.ui.workflow.task.edit")));
final ActionLink taskEditLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.edit")));
final TaskEditForm taskEditForm = new TaskEditForm(m_workflow, m_task);
final ActionLink taskDeleteLink = new ActionLink
(new Label(gz("cms.ui.workflow.task.delete")));
final ActionLink taskDeleteLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.delete")));
final TaskDeleteForm taskDeleteForm = new TaskDeleteForm();
final ActionLink backLink = new ActionLink
(new Label(gz("cms.ui.workflow.task.return")));
final ActionLink backLink = new ActionLink(new Label(gz(
"cms.ui.workflow.task.return")));
backLink.addActionListener(new ResetListener());
m_taskPane = new TaskItemPane(m_workflow, m_task,
@ -114,12 +126,15 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
}
protected class AdminVisible extends VisibilityComponent {
public AdminVisible(final Component child) {
super(child, SecurityManager.WORKFLOW_ADMIN);
super(child, CmsConstants.PRIVILEGE_ADMINISTER_WORKFLOW);
}
}
private class FinishLink extends ActionLink {
FinishLink() {
super(new Label(gz("cms.ui.workflow.task.finish")));
@ -127,27 +142,37 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
addActionListener(new ResetListener());
}
@Override
public final boolean isVisible(final PageState state) {
CmsTask task = m_task.getTask(state);
User lockingUser = task.getLockedUser();
boolean visible = task.isEnabled() &&
(lockingUser == null ||
lockingUser.equals(Web.getWebContext().getUser()));
final CmsTask task = m_task.getTask(state);
final User lockingUser = task.getLockingUser();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
final User currentUser = shiro.getUser();
boolean visible = task.isLocked()
&& (lockingUser == null
|| lockingUser.equals(currentUser));
return visible;
}
private class Listener implements ActionListener {
public final void actionPerformed(final ActionEvent e) {
final PageState state = e.getPageState();
try {
m_task.getTask(state).finish
(Web.getWebContext().getUser());
} catch (TaskException te) {
throw new UncheckedWrapperException(te);
}
@Override
public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final WorkflowManager workflowManager = cdiUtil.findBean(
WorkflowManager.class);
final Task task = m_task.getTask(state);
task.setTaskState("finished");
}
}
}
public void reset(final PageState state) {
@ -157,32 +182,48 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
}
private class TaskDeleteForm extends BaseDeleteForm {
TaskDeleteForm() {
super(new Label(gz("cms.ui.workflow.task.delete_prompt")));
addSecurityListener(SecurityManager.WORKFLOW_ADMIN);
addSecurityListener(CmsConstants.PRIVILEGE_ADMINISTER_WORKFLOW);
}
public final void process(final FormSectionEvent e)
throws FormProcessException {
final PageState state = e.getPageState();
@Override
public final void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
m_task.getTask(state).delete();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final TaskRepository taskRepo = cdiUtil.findBean(
TaskRepository.class);
final Task task = m_task.getTask(state);
taskRepo.delete(task);
m_tasks.getRowSelectionModel().clearSelection(state);
}
}
private class TaskSelectionRequestLocal extends TaskRequestLocal {
protected final Object initialValue(final PageState state) {
final String id = m_tasks.getRowSelectionModel().getSelectedKey
(state).toString();
return new CmsTask(new BigDecimal(id));
@Override
protected final Object initialValue(final PageState state) {
final String id = m_tasks.getRowSelectionModel().getSelectedKey(
state).toString();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CmsTaskTypeRepository taskRepo = cdiUtil.findBean(
CmsTaskTypeRepository.class);
return taskRepo.findById(Long.parseLong(id));
}
}
class SummarySection extends Section {
SummarySection(final ActionLink editLink,
final ActionLink deleteLink) {
setHeading(new Label(gz("cms.ui.workflow.details")));
@ -200,26 +241,35 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
}
private class Properties extends PropertyList {
protected final java.util.List properties(final PageState state) {
final java.util.List props = super.properties(state);
@Override
protected final List<Property> properties(final PageState state) {
@SuppressWarnings("unchecked")
final List<Property> props = super.properties(state);
final Workflow flow = (Workflow) m_workflow.get(state);
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Locale defaultLocale = kernelConfig.getDefaultLocale();
props.add(new Property(gz("cms.ui.name"),
flow.getLabel()));
props.add(new Property(gz("cms.ui.description"),
flow.getDescription()));
props.add(new Property(gz("cms.ui.workflow.current_state"),
flow.getStateString()));
flow.getName().getValue(defaultLocale)));
props.add(new Property(
gz("cms.ui.description"),
flow.getDescription().getValue(defaultLocale)));
// props.add(new Property(gz("cms.ui.workflow.current_state"),
// flow.getStateString()));
props.add(new Property(gz("cms.ui.workflow.num_tasks"),
String.valueOf(flow.getTaskCount())));
String.valueOf(flow.getTasks().size())));
return props;
}
}
}
class TaskSection extends Section {
TaskSection(final ActionLink taskAddLink) {
setHeading(new Label(gz("cms.ui.workflow.tasks")));
@ -229,10 +279,11 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
group.setSubject(m_tasks);
group.addAction(new AdminVisible(taskAddLink), ActionGroup.ADD);
}
}
// XXX Fix this.
private static final String[] s_columns = new String[] {
private static final String[] s_columns = new String[]{
lz("cms.ui.name"),
lz("cms.ui.description"),
lz("cms.ui.workflow.task.dependencies"),
@ -240,14 +291,15 @@ abstract class BaseWorkflowItemPane extends BaseItemPane {
};
private class TaskTable extends Table {
public TaskTable() {
super(new TaskTableModelBuilder(m_workflow), s_columns);
setEmptyView(new Label(gz("cms.ui.workflow.task.none")));
getColumn(0).setCellRenderer
(new DefaultTableCellRenderer(true));
getColumn(0).setCellRenderer(new DefaultTableCellRenderer(true));
}
}
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.workflow;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.kernel.KernelConfig;
import org.librecms.workflow.CmsTask;
import org.librecms.workflow.CmsTaskType;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.workflow.Task;
import org.libreccm.workflow.TaskRepository;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowManager;
import org.librecms.workflow.CmsTaskTypeRepository;
import java.util.List;
import java.util.Locale;
import java.util.TooManyListenersException;
/**
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @author Justin Ross
*/
class TaskAddForm extends BaseTaskForm {
protected final static String ERROR_MSG
= "A workflow template with that name already exists in this content "
+ "section.";
private final SingleSelectionModel<Long> m_model;
public TaskAddForm(final WorkflowRequestLocal workflow,
final SingleSelectionModel<Long> model) {
super("task", gz("cms.ui.workflow.task.add"), workflow);
m_model = model;
try {
m_deps.addPrintListener(new DependencyPrinter());
} catch (TooManyListenersException tmle) {
throw new UncheckedWrapperException(tmle);
}
addProcessListener(new ProcessListener());
}
private class DependencyPrinter implements PrintListener {
@Override
public final void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final List<Task> tasks = m_workflow.getWorkflow(state).getTasks();
final OptionGroup options = (OptionGroup) event.getTarget();
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Locale defaultLocale = kernelConfig.getDefaultLocale();
tasks.forEach(task -> options.addOption(new Option(
Long.toString(task.getTaskId()),
task.getLabel().getValue(defaultLocale))));
}
}
private class ProcessListener implements FormProcessListener {
@Override
public final void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
final Workflow workflow = m_workflow.getWorkflow(state);
final CmsTask task = new CmsTask();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final TaskRepository taskRepo = cdiUtil.findBean(
TaskRepository.class);
final CmsTaskTypeRepository taskTypeRepo = cdiUtil.findBean(CmsTaskTypeRepository.class);
final WorkflowManager workflowManager = cdiUtil.findBean(
WorkflowManager.class);
final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class);
final Locale defaultLocale = kernelConfig.getDefaultLocale();
task.getLabel().addValue(defaultLocale,
((String) m_name.getValue(state)));
task.getDescription().addValue(
defaultLocale,
((String) m_description.getValue(state)));
final CmsTaskType taskType = taskTypeRepo.findById((Long) m_type.getValue(state));
task.setTaskType(taskType);
task.setActive(true);
taskRepo.save(task);
workflowManager.addTask(workflow, task);
processDependencies(task, (String[]) m_deps.getValue(state));
m_model.setSelectedKey(state, task.getTaskId());
}
}
}

View File

@ -0,0 +1,156 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.workflow;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.kernel.KernelConfig;
import org.librecms.workflow.CmsTask;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.workflow.Task;
import org.libreccm.workflow.TaskRepository;
import org.librecms.workflow.CmsTaskType;
import org.librecms.workflow.CmsTaskTypeRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TooManyListenersException;
/**
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @author Justin Ross
*/
class TaskEditForm extends BaseTaskForm {
private TaskRequestLocal m_task;
public TaskEditForm(final WorkflowRequestLocal workflow,
final TaskRequestLocal task) {
super("task", gz("cms.ui.workflow.task.edit"), workflow);
m_task = task;
try {
m_deps.addPrintListener(new DependencyPrinter());
} catch (TooManyListenersException tmle) {
throw new UncheckedWrapperException(tmle);
}
addInitListener(new InitListener());
addProcessListener(new ProcessListener());
}
private class DependencyPrinter implements PrintListener {
@Override
public final void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final List<Task> tasks = m_workflow.getWorkflow(state).getTasks();
final OptionGroup options = (OptionGroup) event.getTarget();
tasks.forEach(task -> addOption(task, state, options));
}
}
private void addOption(final Task task,
final PageState state,
final OptionGroup options) {
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Locale defaultLocale = kernelConfig.getDefaultLocale();
if (m_task.getTask(state).getTaskId() != task.getTaskId()) {
options.addOption(new Option(
Long.toString(task.getTaskId()),
task.getLabel().getValue(defaultLocale)));
}
}
private class InitListener implements FormInitListener {
@Override
public final void init(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
final CmsTask task = m_task.getTask(state);
m_name.setValue(state, task.getLabel());
m_description.setValue(state, task.getDescription());
m_type.setValue(state, Long.toString(task.getTaskType()
.getTaskTypeId()));
final List<Task> deps = task.getDependsOn();
final List<String> list = new ArrayList<>();
deps.forEach(dep -> list.add(Long.toString(dep.getTaskId())));
m_deps.setValue(state, list.toArray());
}
}
private class ProcessListener implements FormProcessListener {
@Override
public final void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
final CmsTask task = m_task.getTask(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final TaskRepository taskRepo = cdiUtil.findBean(
TaskRepository.class);
final CmsTaskTypeRepository taskTypeRepo = cdiUtil.findBean(CmsTaskTypeRepository.class);
final ConfigurationManager confManager = cdiUtil.findBean(
ConfigurationManager.class);
final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class);
final Locale defaultLocale = kernelConfig.getDefaultLocale();
task.getLabel().addValue(defaultLocale,
(String) m_name.getValue(state));
task.getDescription().addValue(
defaultLocale,
(String) m_description.getValue(state));
final CmsTaskType taskType = taskTypeRepo.findById((Long) m_type.getValue(state));
task.setTaskType(taskType);
taskRepo.save(task);
processDependencies(task, (String[]) m_deps.getValue(state));
}
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.workflow;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.util.Assert;
import com.arsdigita.util.GraphSet;
import com.arsdigita.util.Graphs;
import org.apache.logging.log4j.LogManager;
import org.libreccm.workflow.Task;
import org.libreccm.workflow.Workflow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.Logger;
class TaskTableModelBuilder extends AbstractTableModelBuilder {
private static final Logger LOGGER = LogManager.getLogger(
TaskTableModelBuilder.class);
private final WorkflowRequestLocal m_workflow;
TaskTableModelBuilder(final WorkflowRequestLocal workflow) {
m_workflow = workflow;
}
@Override
public final TableModel makeModel(final Table table,
final PageState state) {
LOGGER.debug("Creating a new table model for the current request");
return new Model(m_workflow.getWorkflow(state));
}
private static class Model implements TableModel {
private Task m_task;
private Iterator m_tasks;
private Map m_dependencies = new HashMap();
private Model(final Workflow workflow) {
final Iterator<Task> tasksIter = workflow.getTasks().iterator();
GraphSet g = new GraphSet();
while (tasksIter.hasNext()) {
Task t = tasksIter.next();
final Iterator<Task> deps = t.getDependsOn().iterator();
final StringBuffer buffer = new StringBuffer();
while (deps.hasNext()) {
Task dep = deps.next();
g.addEdge(t, dep, null);
buffer.append(dep.getLabel() + ", ");
}
final int len = buffer.length();
if (len >= 2) {
buffer.setLength(len - 2);
} else {
g.addNode(t);
}
m_dependencies.put(t, buffer.toString());
}
List tasks = new ArrayList();
outer:
while (g.nodeCount() > 0) {
List l = Graphs.getSinkNodes(g);
for (Iterator it = l.iterator(); it.hasNext();) {
Task t = (Task) it.next();
tasks.add(t);
g.removeNode(t);
continue outer;
}
// break loop if no nodes removed
LOGGER.error("found possible loop in tasks for " + workflow);
break;
}
Assert.assertEquals(workflow.getTasks().size(), tasks.size());
m_tasks = tasks.iterator();
}
@Override
public final int getColumnCount() {
return 4;
}
@Override
public final boolean nextRow() {
if (m_tasks.hasNext()) {
m_task = (Task) m_tasks.next();
return true;
} else {
return false;
}
}
@Override
public final Object getKeyAt(final int column) {
return m_task.getTaskId();
}
@Override
public final Object getElementAt(final int column) {
switch (column) {
case 0:
return m_task.getLabel();
case 1:
return m_task.getDescription();
case 2:
return m_dependencies.get(m_task);
case 3:
return "";
// return m_task.getStateString();
default:
throw new IllegalStateException();
}
}
}
}

View File

@ -26,7 +26,12 @@ import com.arsdigita.cms.ui.BaseAdminPane;
import com.arsdigita.cms.ui.BaseDeleteForm;
import com.arsdigita.cms.ui.VisibilityComponent;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.workflow.Workflow;
import org.libreccm.workflow.WorkflowManager;
import org.libreccm.workflow.WorkflowRepository;
import org.libreccm.workflow.WorkflowTemplate;
import org.libreccm.workflow.WorkflowTemplateRepository;
import org.librecms.CmsConstants;
import java.math.BigDecimal;
@ -67,11 +72,15 @@ public final class WorkflowAdminPane extends BaseAdminPane {
}
@Override
public final void process(final FormSectionEvent e)
public final void process(final FormSectionEvent event)
throws FormProcessException {
final PageState state = e.getPageState();
final PageState state = event.getPageState();
m_workflow.getWorkflow(state).delete();
final CdiUtil cdiUtil= CdiUtil.createCdiUtil();
final WorkflowRepository workflowRepo= cdiUtil.findBean(WorkflowRepository.class);
final Workflow workflow = m_workflow.getWorkflow(state);
workflowRepo.delete(workflow);
getSelectionModel().clearSelection(state);
}
@ -80,11 +89,16 @@ public final class WorkflowAdminPane extends BaseAdminPane {
private class SelectionRequestLocal extends WorkflowRequestLocal {
@Override
protected final Object initialValue(final PageState state) {
final String id = getSelectionModel().getSelectedKey(state)
.toString();
return new WorkflowTemplate(new BigDecimal(id));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final WorkflowTemplateRepository templateRepo = cdiUtil.findBean(
WorkflowTemplateRepository.class);
return templateRepo.findById(Long.parseLong(id));
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.workflow;
import org.libreccm.core.AbstractEntityRepository;
import javax.enterprise.context.RequestScoped;
/**
* A repository for the {@link CmsTaskType} entity.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class CmsTaskTypeRepository extends AbstractEntityRepository<Long, CmsTaskType>{
@Override
public Class<CmsTaskType> getEntityClass() {
return CmsTaskType.class;
}
@Override
public boolean isNew(final CmsTaskType taskType) {
return taskType.getTaskTypeId() == 0;
}
}