Initial POC
This commit is contained in:
@@ -14,10 +14,8 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
@@ -58,19 +56,22 @@ import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContext;
|
||||
import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContextProvider;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
|
||||
import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoConf;
|
||||
import org.springframework.ide.vscode.languageserver.starter.LanguageServerRunnerAutoConf;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
@SpringBootConfiguration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration({
|
||||
// During development you can uncomment the below so that boot dash can detect started state properly:
|
||||
// SpringApplicationAdminJmxAutoConfiguration.class,
|
||||
LanguageServerAutoConf.class,
|
||||
LanguageServerRunnerAutoConf.class,
|
||||
ConfigurationPropertiesAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class
|
||||
})
|
||||
//@ImportAutoConfiguration({
|
||||
// // During development you can uncomment the below so that boot dash can detect started state properly:
|
||||
// // SpringApplicationAdminJmxAutoConfiguration.class,
|
||||
// LanguageServerAutoConf.class,
|
||||
// LanguageServerRunnerAutoConf.class,
|
||||
// ConfigurationPropertiesAutoConfiguration.class,
|
||||
// PropertyPlaceholderAutoConfiguration.class,
|
||||
// SprottyAutoConf.class,
|
||||
// WebSocketServletAutoConfiguration.class,
|
||||
// WebMvcAutoConfiguration.class
|
||||
//})
|
||||
@EnableAutoConfiguration
|
||||
@EnableConfigurationProperties(BootLsConfigProperties.class)
|
||||
@ComponentScan
|
||||
public class BootLanguagServerBootApp {
|
||||
@@ -112,6 +113,12 @@ public class BootLanguagServerBootApp {
|
||||
@Bean ValueProviderRegistry valueProviders() {
|
||||
return new ValueProviderRegistry();
|
||||
}
|
||||
|
||||
@Bean ThreadPoolTaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler t = new ThreadPoolTaskScheduler();
|
||||
t.initialize();
|
||||
return t;
|
||||
}
|
||||
|
||||
@Bean InitializingBean initializeValueProviders(ValueProviderRegistry r, @Qualifier("adHocProperties") ProjectBasedPropertyIndexProvider adHocProperties, SourceLinks sourceLinks) {
|
||||
return () -> {
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package org.springframework.ide.vscode.boot.app.diagram;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.sprotty.Dimension;
|
||||
import org.eclipse.sprotty.IDiagramServer;
|
||||
import org.eclipse.sprotty.Point;
|
||||
import org.eclipse.sprotty.SCompartment;
|
||||
import org.eclipse.sprotty.SEdge;
|
||||
import org.eclipse.sprotty.SGraph;
|
||||
import org.eclipse.sprotty.SLabel;
|
||||
import org.eclipse.sprotty.SModelElement;
|
||||
import org.eclipse.sprotty.SModelRoot;
|
||||
import org.eclipse.sprotty.SNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class LiveBeanDiagramModel implements InitializingBean {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LiveBeanDiagramModel.class);
|
||||
|
||||
@Autowired
|
||||
private IDiagramServer diagramServer;
|
||||
|
||||
@Autowired
|
||||
private RunningAppProvider runningAppProvider;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("taskScheduler")
|
||||
private TaskScheduler taskScheduler;
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
taskScheduler.scheduleAtFixedRate(() -> diagramServer.setModel(generateModel()), Duration.ofSeconds(15));
|
||||
}
|
||||
|
||||
private SModelRoot generateModel() {
|
||||
try {
|
||||
Collection<SpringBootApp> apps = runningAppProvider.getAllRunningSpringApps();
|
||||
if (!apps.isEmpty()) {
|
||||
return toSprottyGraph(apps.iterator().next());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("{}", e);
|
||||
}
|
||||
return SGraph.EMPTY_ROOT;
|
||||
}
|
||||
|
||||
private SModelRoot toSprottyGraph(SpringBootApp app) throws Exception {
|
||||
SModelRoot graph = new SModelRoot();
|
||||
graph.setId(app.getProcessName());
|
||||
graph.setType("graph");
|
||||
|
||||
graph.setChildren(new ArrayList<>());
|
||||
List<SModelElement> graphChildren = graph.getChildren();
|
||||
|
||||
LiveBeansModel beansModel = app.getBeans();
|
||||
for (String targetBeanId : beansModel.getBeanNames()) {
|
||||
for (LiveBean bean : beansModel.getBeansOfName(targetBeanId)) {
|
||||
graphChildren.add(createBean(bean.getId(), bean.getShortName(), new Point(), new Dimension()));
|
||||
}
|
||||
for (LiveBean sourceBean : beansModel.getBeansDependingOn(targetBeanId)) {
|
||||
graphChildren.add(createEdge(sourceBean.getId() + " " + targetBeanId, sourceBean.getId(), targetBeanId));
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
private static SNode createBean(String id, String labelText, Point location, Dimension size) {
|
||||
SNode node = new SNode();
|
||||
node.setId(id);
|
||||
node.setType("node:bean");
|
||||
node.setLayout("vbox");
|
||||
node.setPosition(new Point(Math.random() * 1024, Math.random() * 768));
|
||||
node.setSize(new Dimension(80, 80));
|
||||
node.setChildren(new ArrayList<>());
|
||||
|
||||
SCompartment compartment = new SCompartment();
|
||||
compartment.setId(id + "-comp");
|
||||
compartment.setType("compartment");
|
||||
compartment.setLayout("hbox");
|
||||
compartment.setChildren(new ArrayList<>());
|
||||
|
||||
SLabel label = new SLabel();
|
||||
label.setId(id + "-lanbel");
|
||||
label.setType("node:label");
|
||||
label.setText(labelText);
|
||||
|
||||
compartment.getChildren().add(label);
|
||||
node.getChildren().add(compartment);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private static SEdge createEdge(String id, String sourceId, String targetId) {
|
||||
SEdge edge = new SEdge();
|
||||
edge.setId(id);
|
||||
edge.setType("edge:straight");
|
||||
edge.setSourceId(sourceId);
|
||||
edge.setTargetId(targetId);
|
||||
return edge;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.springframework.ide.vscode.boot.app.diagram;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.sprotty.Dimension;
|
||||
import org.eclipse.sprotty.IDiagramServer;
|
||||
import org.eclipse.sprotty.Point;
|
||||
import org.eclipse.sprotty.SCompartment;
|
||||
import org.eclipse.sprotty.SEdge;
|
||||
import org.eclipse.sprotty.SLabel;
|
||||
import org.eclipse.sprotty.SModelRoot;
|
||||
import org.eclipse.sprotty.SNode;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import net.bytebuddy.utility.RandomString;
|
||||
|
||||
|
||||
@Component
|
||||
public class MockDiagramServerModel implements InitializingBean {
|
||||
|
||||
@Autowired
|
||||
IDiagramServer diagramServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("taskScheduler")
|
||||
private TaskScheduler taskScheduler;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// taskScheduler.scheduleAtFixedRate(() -> diagramServer.setModel(generateModel()), Duration.ofSeconds(5));
|
||||
diagramServer.setModel(generateModel(10));
|
||||
}
|
||||
|
||||
public static SModelRoot generateModel(int nodesNum) {
|
||||
SModelRoot graph = new SModelRoot();
|
||||
graph.setId("graph");
|
||||
graph.setType("graph");
|
||||
|
||||
SNode node0 = createBean("node0", "main", new Point(100, 100), new Dimension(120, 40));
|
||||
|
||||
graph.setChildren(new ArrayList<>());
|
||||
graph.getChildren().add(node0);
|
||||
|
||||
for (int i = 1; i < nodesNum; i++) {
|
||||
SNode node = createBean("node" + i, RandomString.make(((int) Math.round(Math.random()* 10 + 1))), new Point(Math.random() * 1024, Math.random() * 768), new Dimension(120, 40));
|
||||
SEdge edge = createEdge("edge-" + i, node0.getId(), node.getId());
|
||||
graph.getChildren().add(edge);
|
||||
graph.getChildren().add(node);
|
||||
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
private static SNode createBean(String id, String labelText, Point location, Dimension size) {
|
||||
SNode node = new SNode();
|
||||
node.setId(id);
|
||||
node.setType("node:bean");
|
||||
node.setLayout("vbox");
|
||||
node.setPosition(new Point(Math.random() * 1024, Math.random() * 768));
|
||||
node.setSize(new Dimension(80, 80));
|
||||
node.setChildren(new ArrayList<>());
|
||||
|
||||
SCompartment compartment = new SCompartment();
|
||||
compartment.setId(id + "-comp");
|
||||
compartment.setType("compartment");
|
||||
compartment.setLayout("hbox");
|
||||
compartment.setChildren(new ArrayList<>());
|
||||
|
||||
SLabel label = new SLabel();
|
||||
label.setId(id + "-lanbel");
|
||||
label.setType("node:label");
|
||||
label.setText(labelText);
|
||||
|
||||
compartment.getChildren().add(label);
|
||||
node.getChildren().add(compartment);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private static SEdge createEdge(String id, String sourceId, String targetId) {
|
||||
SEdge edge = new SEdge();
|
||||
edge.setId(id);
|
||||
edge.setType("edge:straight");
|
||||
edge.setSourceId(sourceId);
|
||||
edge.setTargetId(targetId);
|
||||
return edge;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.springframework.ide.vscode.boot.app.diagram;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.sprotty.IDiagramServer;
|
||||
import org.eclipse.sprotty.IPopupModelFactory;
|
||||
import org.eclipse.sprotty.RequestPopupModelAction;
|
||||
import org.eclipse.sprotty.SGraph;
|
||||
import org.eclipse.sprotty.SLabel;
|
||||
import org.eclipse.sprotty.SModelElement;
|
||||
import org.eclipse.sprotty.SModelRoot;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class PopupModelFactory implements IPopupModelFactory {
|
||||
|
||||
@Override
|
||||
public SModelRoot createPopupModel(SModelElement element, RequestPopupModelAction request, IDiagramServer server) {
|
||||
|
||||
SGraph graph = new SGraph();
|
||||
graph.setId("popup");
|
||||
List<SModelElement> children = new ArrayList<>();
|
||||
|
||||
SLabel label = new SLabel();
|
||||
label.setType("node:label");
|
||||
label.setText("I'm a tooltip!");
|
||||
children.add(label);
|
||||
|
||||
graph.setChildren(children);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,4 +8,4 @@ spring.main.banner-mode: off
|
||||
#logging.level.org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer=debug
|
||||
#logging.level.org.springframework.ide.vscode.boot.java.utils.SpringIndexerJava=debug
|
||||
#logging.level.org.springframework.ide.vscode.boot.app.SpringSymbolIndex=debug
|
||||
#logging.level.org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp=off
|
||||
logging.level.org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp=off
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,46 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2017-2018 TypeFox and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* This Source Code may also be made available under the following Secondary
|
||||
* Licenses when the conditions for such availability set forth in the Eclipse
|
||||
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
||||
* with the GNU Classpath Exception which is available at
|
||||
* https://www.gnu.org/software/classpath/license.html.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
||||
********************************************************************************/
|
||||
|
||||
.sprotty-node {
|
||||
fill: #aae;
|
||||
stroke: #66b;
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
.sprotty-text {
|
||||
font-size: 16pt;
|
||||
text-anchor: middle;
|
||||
}
|
||||
|
||||
.sprotty-edge {
|
||||
fill: none;
|
||||
stroke: #488;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.sprotty-node.selected {
|
||||
stroke: #dd8;
|
||||
stroke-width: 6;
|
||||
}
|
||||
|
||||
.sprotty-missing {
|
||||
stroke-width: 1;
|
||||
stroke: #f00;
|
||||
fill: #f00;
|
||||
font-family: SansSerif;
|
||||
font-size: 14pt;
|
||||
text-anchor: middle;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2017-2018 TypeFox and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* This Source Code may also be made available under the following Secondary
|
||||
* Licenses when the conditions for such availability set forth in the Eclipse
|
||||
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
||||
* with the GNU Classpath Exception which is available at
|
||||
* https://www.gnu.org/software/classpath/license.html.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
||||
********************************************************************************/
|
||||
|
||||
.copyright {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
font-size: 10px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.help {
|
||||
margin-top: 24px;
|
||||
text-align: right;
|
||||
font-size: 16px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #bbb;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>sprotty Circles Example</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/page.css">
|
||||
<!-- support Microsoft browsers -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dom4/3.0.0/dom4.js">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row" id="sprotty-app" data-app="circlegraph">
|
||||
<div class="col-md-10">
|
||||
<h1>sprotty Circles Example</h1>
|
||||
<p>
|
||||
<button id="refresh">Refresh</button>
|
||||
<button id="scrambleNodes">Scramble nodes</button>
|
||||
</p>
|
||||
</div>
|
||||
<div class="help col-md-2">
|
||||
<a href='https://github.com/theia-ide/sprotty/wiki/Using-sprotty'>Help</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="spring-boot" class="sprotty"/>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
© 2017 <a href="http://typefox.io">TypeFox GmbH</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="bundle.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.springframework.ide.vscode.boot.test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.elk.alg.layered.options.LayeredMetaDataProvider;
|
||||
import org.eclipse.elk.core.RecursiveGraphLayoutEngine;
|
||||
import org.eclipse.elk.core.data.LayoutMetaDataService;
|
||||
import org.eclipse.elk.core.util.BasicProgressMonitor;
|
||||
import org.eclipse.elk.graph.ElkNode;
|
||||
import org.eclipse.sprotty.Point;
|
||||
import org.eclipse.sprotty.SModelRoot;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.app.diagram.MockDiagramServerModel;
|
||||
import org.springframework.ide.vscode.commons.sprotty.elk.ElkUtils;
|
||||
|
||||
|
||||
public class LayoutTest {
|
||||
|
||||
@Test
|
||||
public void testCreateGraph() throws Exception {
|
||||
SModelRoot modelRoot = MockDiagramServerModel.generateModel(10);
|
||||
ElkNode graph = new ElkUtils(modelRoot).graph;
|
||||
assertNotNull(graph);
|
||||
assertEquals(10, graph.getChildren().size());
|
||||
assertEquals(9, graph.getContainedEdges().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLayout() throws Exception {
|
||||
LayoutMetaDataService.getInstance().registerLayoutMetaDataProviders(new LayeredMetaDataProvider());
|
||||
|
||||
SModelRoot modelRoot = MockDiagramServerModel.generateModel(10);
|
||||
ElkNode graph = new ElkUtils(modelRoot).graph;
|
||||
|
||||
Map<String, Point> locations = new HashMap<>();
|
||||
|
||||
for (ElkNode child : graph.getChildren()) {
|
||||
locations.put(child.getIdentifier(), new Point(child.getX(), child.getY()));
|
||||
}
|
||||
|
||||
new RecursiveGraphLayoutEngine().layout(graph, new BasicProgressMonitor());
|
||||
|
||||
for (ElkNode child : graph.getChildren()) {
|
||||
assertNotEquals(locations.get(child.getIdentifier()), new Point(child.getX(), child.getY()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user