Skip to content

Commit

Permalink
JBPM-9597: [BPMN] Open subprocesses in a new editor (BC only) (#3596)
Browse files Browse the repository at this point in the history
  • Loading branch information
hasys committed Mar 25, 2021
1 parent dc407ab commit b1cc5c7
Show file tree
Hide file tree
Showing 14 changed files with 673 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ public interface StunnerCommonIconsGlyphFactory {
ImageStripGlyph GEARS = ImageStripGlyph.create(StunnerCommonIconsStrip.class, 1);

ImageStripGlyph FORM = ImageStripGlyph.create(StunnerCommonIconsStrip.class, 2);

ImageStripGlyph SUBPROCESS = ImageStripGlyph.create(StunnerCommonIconsStrip.class, 2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ public class StunnerProjectClientConstants {
public static final String DIAGRAM_PARSING_ERROR = "org.kie.workbench.common.stunner.project.client.editor.DiagramParsingError";

public static final String DOCUMENTATION = "org.kie.workbench.common.stunner.project.client.editor.Documentation";

public static final String OPEN_SUBPROCESS = "org.kie.workbench.common.stunner.project.client.component.toolbox.OpenSubprocessToolboxAction";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.stunner.bpmn.client.util;

import org.kie.workbench.common.stunner.bpmn.definition.ReusableSubprocess;
import org.kie.workbench.common.stunner.core.graph.Element;
import org.kie.workbench.common.stunner.core.graph.content.view.View;

public class GraphUtils {

@SuppressWarnings("unchecked")
public static boolean isReusableSubProcess(final Element<?> element) {
return null != element.asNode() &&
element.getContent() instanceof View &&
((Element<View<?>>) element).getContent().getDefinition() instanceof ReusableSubprocess;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.stunner.bpmn.client.util;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.workbench.common.stunner.bpmn.definition.ReusableSubprocess;
import org.kie.workbench.common.stunner.bpmn.definition.UserTask;
import org.kie.workbench.common.stunner.core.graph.Element;
import org.kie.workbench.common.stunner.core.graph.content.Bounds;
import org.kie.workbench.common.stunner.core.graph.content.view.View;
import org.kie.workbench.common.stunner.core.graph.content.view.ViewImpl;
import org.kie.workbench.common.stunner.core.graph.impl.NodeImpl;
import org.mockito.junit.MockitoJUnitRunner;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

@RunWith(MockitoJUnitRunner.class)
public class GraphUtilsTest {

@Test
public void testContentIsNotSet() {
Element<Object> element = mock(Element.class);
assertFalse(GraphUtils.isReusableSubProcess(element));
}

@Test
public void testNonView() {
Element<Object> element = new NodeImpl<>("UUID");
element.setContent(new Object());
assertFalse(GraphUtils.isReusableSubProcess(element));
}

@Test
public void testNonReusableSubprocess() {
Element<View<UserTask>> element = new NodeImpl<>("UUID");
View<UserTask> userTaskView = new ViewImpl<>(new UserTask(), Bounds.create());
element.setContent(userTaskView);
assertFalse(GraphUtils.isReusableSubProcess(element));
}

@Test
public void testReusableSubprocess() {
Element<View<ReusableSubprocess>> element = new NodeImpl<>("UUID");
View<ReusableSubprocess> reusableSubprocessView = new ViewImpl<>(new ReusableSubprocess(), Bounds.create());
element.setContent(reusableSubprocessView);
assertTrue(GraphUtils.isReusableSubProcess(element));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.stunner.bpmn.project.service;

import java.util.List;

import org.jboss.errai.bus.server.annotations.Remote;

@Remote
public interface ProjectOpenReusableSubprocessService {
List<String> openReusableSubprocess(String processId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.stunner.bpmn.project.backend.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import org.jboss.errai.bus.server.annotations.Service;
import org.kie.soup.commons.util.Sets;
import org.kie.workbench.common.services.refactoring.model.index.terms.valueterms.ValueIndexTerm;
import org.kie.workbench.common.services.refactoring.model.index.terms.valueterms.ValueResourceIndexTerm;
import org.kie.workbench.common.services.refactoring.service.RefactoringQueryService;
import org.kie.workbench.common.services.refactoring.service.ResourceType;
import org.kie.workbench.common.stunner.bpmn.project.backend.query.FindBpmnProcessIdsQuery;
import org.kie.workbench.common.stunner.bpmn.project.service.ProjectOpenReusableSubprocessService;
import org.uberfire.backend.vfs.Path;

@ApplicationScoped
@Service
public class ProjectOpenReusableSubprocessServiceImpl implements ProjectOpenReusableSubprocessService {

private final RefactoringQueryService queryService;
private final Supplier<ResourceType> resourceType;
private final Supplier<String> queryName;
private final Set<ValueIndexTerm> queryTerms;

// CDI proxy.
protected ProjectOpenReusableSubprocessServiceImpl() {
this(null);
}

@Inject
public ProjectOpenReusableSubprocessServiceImpl(final RefactoringQueryService queryService) {
this.queryService = queryService;
this.resourceType = () -> ResourceType.BPMN2;
this.queryName = () -> FindBpmnProcessIdsQuery.NAME;
this.queryTerms = new Sets.Builder<ValueIndexTerm>()
.add(new ValueResourceIndexTerm("*",
resourceType.get(),
ValueIndexTerm.TermSearchType.WILDCARD))
.build();
}

String getQueryName() {
return queryName.get();
}

Set<ValueIndexTerm> createQueryTerms() {
return queryTerms;
}

@Override
@SuppressWarnings("unchecked")
public List<String> openReusableSubprocess(String processId) {
List<String> answer = new ArrayList<>();
Map<String, Path> subprocesses = queryService
.query(getQueryName(), createQueryTerms())
.stream()
.map(row -> (Map<String, Path>) row.getValue())
.filter(row -> row.get(processId) != null)
.findFirst()
.orElse(null);

if (subprocesses == null) {
return answer;
}

answer.add(subprocesses.get(processId).getFileName());
answer.add(subprocesses.get(processId).toURI());
return answer;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates.
*
* 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 org.kie.workbench.common.stunner.bpmn.project.backend.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.workbench.common.services.refactoring.model.query.RefactoringPageRow;
import org.kie.workbench.common.services.refactoring.service.RefactoringQueryService;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.uberfire.backend.vfs.Path;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ProjectOpenReusableSubprocessServiceImplTest {

private final static String PROCESS_ID = "processId";
private final static String NOT_REGISTERED_PROCESS_ID = "not_registered_process_id";
private final static String PROCESS_FILE_NAME = "File Name";
private final static String PROCESS_URI = "URI";

@Mock
private RefactoringQueryService serviceQuery;
@Mock
private Path path;

private ProjectOpenReusableSubprocessServiceImpl service;
private List<RefactoringPageRow> rows;

@Before
public void setUp() {
when(path.getFileName()).thenReturn(PROCESS_FILE_NAME);
when(path.toURI()).thenReturn(PROCESS_URI);

RefactoringPageRow<Map<String, Path>> row = new RefactoringPageRow<Map<String, Path>>() {
@Override
public void setValue(Map<String, Path> value) {
super.setValue(value);
}

@Override
public Map<String, Path> getValue() {
Map<String, Path> subprocess = new HashMap<>();
subprocess.put(PROCESS_ID, path);
return subprocess;
}
};

rows = new ArrayList<>();
rows.add(row);

service = new ProjectOpenReusableSubprocessServiceImpl(serviceQuery);
}

@Test
public void testNotFound() {
assertTrue(service.openReusableSubprocess(PROCESS_ID).isEmpty());
}

@Test
public void testReusableSubprocessFound() {
when(serviceQuery.query(service.getQueryName(), service.createQueryTerms())).thenReturn(rows);

List<String> answer = service.openReusableSubprocess(PROCESS_ID);
assertEquals(2, answer.size());
assertEquals(PROCESS_FILE_NAME, answer.get(0));
assertEquals(PROCESS_URI, answer.get(1));
}

@Test
public void testProcessWithIdNotFound() {
when(serviceQuery.query(service.getQueryName(), service.createQueryTerms())).thenReturn(rows);

List<String> answer = service.openReusableSubprocess(NOT_REGISTERED_PROCESS_ID);
assertEquals(0, answer.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import org.jboss.errai.ioc.client.api.ManagedInstance;
import org.kie.workbench.common.stunner.bpmn.client.forms.util.BPMNFormsContextUtils;
import org.kie.workbench.common.stunner.bpmn.client.util.GraphUtils;
import org.kie.workbench.common.stunner.bpmn.project.client.toolbox.OpenSubprocessToolboxAction;
import org.kie.workbench.common.stunner.bpmn.qualifiers.BPMN;
import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler;
import org.kie.workbench.common.stunner.core.client.components.toolbox.actions.AbstractActionsToolboxFactory;
Expand All @@ -47,14 +49,17 @@ public class BPMNProjectActionsToolboxFactory extends AbstractActionsToolboxFact

private final ActionsToolboxFactory commonActionToolbox;
private final ManagedInstance<FormGenerationToolboxAction> generateFormsActions;
private final ManagedInstance<OpenSubprocessToolboxAction> openSubprocessActions;
private final ManagedInstance<ActionsToolboxView> views;

@Inject
public BPMNProjectActionsToolboxFactory(final @CommonActionsToolbox ActionsToolboxFactory commonActionToolbox,
final @Any ManagedInstance<FormGenerationToolboxAction> generateFormsActions,
final @Any ManagedInstance<OpenSubprocessToolboxAction> openSubprocessActions,
final @Any @CommonActionsToolbox ManagedInstance<ActionsToolboxView> views) {
this.commonActionToolbox = commonActionToolbox;
this.generateFormsActions = generateFormsActions;
this.openSubprocessActions = openSubprocessActions;
this.views = views;
}

Expand All @@ -71,12 +76,16 @@ public Collection<ToolboxAction<AbstractCanvasHandler>> getActions(final Abstrac
if (BPMNFormsContextUtils.isFormGenerationSupported(e)) {
actions.add(generateFormsActions.get());
}
if (GraphUtils.isReusableSubProcess(e)) {
actions.add(openSubprocessActions.get());
}
return actions;
}

@PreDestroy
public void destroy() {
generateFormsActions.destroyAll();
openSubprocessActions.destroyAll();
views.destroyAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public interface BPMNClientConstants {
@TranslationKey(defaultValue = "An error was produced during migration")
String EditorMigrateErrorGeneric = "editor.actions.migrateErrorGeneric";

@TranslationKey(defaultValue = "An error was produced during diagram svg file generation")
@TranslationKey(defaultValue = "An error was produced during diagram svg file generation")
String EditorGenerateSvgFileError = "editor.error.generateSvgFileError";

@TranslationKey(defaultValue = "Subprocess {0} not found.")
String SubprocessNotFound = "editor.error.subprocessNotFound";

@TranslationKey(defaultValue = "Subprocess ID is not specified.")
String SubprocessIdNotSpecified = "editor.error.subprocessNotSpecified";

@TranslationKey(defaultValue = "Open Sub-process")
String OpenSubprocessToolBoxAction = "editor.toolbox.openSubprocessToolboxAction";
}

0 comments on commit b1cc5c7

Please sign in to comment.