Initial POC

This commit is contained in:
BoykoAlex
2019-08-21 10:40:56 -04:00
parent 0714b6a693
commit 83193e5d42
22 changed files with 34418 additions and 16 deletions

View File

@@ -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 () -> {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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">
&copy; 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>

View File

@@ -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()));
}
}
}