Skip to content

Commit c365e18

Browse files
committed
ST6RI-682 Added Pull project download capability to Eclipse IDE
1 parent c315a19 commit c365e18

6 files changed

Lines changed: 219 additions & 29 deletions

File tree

org.omg.sysml.xtext.ui/plugin.xml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
</adapt>
6363
</iterate>
6464
</activeWhen>
65+
</handler>
66+
<handler
67+
class="org.omg.sysml.xtext.ui.SysMLExecutableExtensionFactory:org.omg.sysml.xtext.ui.handlers.PullRepositoryProject"
68+
commandId="org.omg.sysml.xtext.ui.PullRepositoryProject">
6569
</handler>
6670
</extension>
6771
<extension point="org.eclipse.core.expressions.definitions">
@@ -151,6 +155,10 @@
151155
<command
152156
id="org.omg.sysml.xtext.ui.GenerateLibraryIndex"
153157
name="Generate Library Index">
158+
</command>
159+
<command
160+
id="org.omg.sysml.xtext.ui.PullRepositoryProject"
161+
name="Pull remote">
154162
</command>
155163
</extension>
156164
<extension point="org.eclipse.ui.menus">
@@ -365,6 +373,15 @@
365373
</and>
366374
</visibleWhen>
367375
</command>
376+
</menuContribution>
377+
<menuContribution
378+
allPopups="false"
379+
locationURI="popup:org.eclipse.ui.popup.any?after=additions">
380+
<command
381+
commandId="org.omg.sysml.xtext.ui.PullRepositoryProject"
382+
label="Pull remote"
383+
style="push">
384+
</command>
368385
</menuContribution>
369386
</extension>
370387
<extension point="org.eclipse.compare.contentViewers">
@@ -400,7 +417,7 @@
400417
<extension
401418
point="org.eclipse.xtext.extension_resourceServiceProvider">
402419
<resourceServiceProvider
403-
class="org.omg.sysml.xtext.ui.xmi.SysMLXExecutableExtensionFactory:org.eclipse.xtext.ui.resource.generic.EmfResourceUIServiceProvider"
420+
class="org.omg.sysml.xtext.ui.xmi.SysMLxExecutableExtensionFactory:org.eclipse.xtext.ui.resource.generic.EmfResourceUIServiceProvider"
404421
uriExtension="sysmlx">
405422
</resourceServiceProvider>
406423
</extension>
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
* SysML 2 Pilot Implementation
3+
* Copyright (C) 2025 Model Driven Solutions, Inc.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* @license LGPL-3.0-or-later <http://spdx.org/licenses/LGPL-3.0-or-later>
19+
*
20+
* Contributors:
21+
* Laszlo Gati, MDS
22+
*/
23+
package org.omg.sysml.xtext.ui.handlers;
24+
25+
import java.io.IOException;
26+
import java.util.Collection;
27+
import java.util.HashSet;
28+
import java.util.Map;
29+
import java.util.Optional;
30+
import java.util.Properties;
31+
import java.util.Set;
32+
import java.util.stream.Stream;
33+
34+
import org.eclipse.core.commands.AbstractHandler;
35+
import org.eclipse.core.commands.ExecutionEvent;
36+
import org.eclipse.core.commands.ExecutionException;
37+
import org.eclipse.core.resources.IContainer;
38+
import org.eclipse.core.resources.IFile;
39+
import org.eclipse.core.resources.IProject;
40+
import org.eclipse.core.resources.IResource;
41+
import org.eclipse.core.resources.WorkspaceJob;
42+
import org.eclipse.core.runtime.CoreException;
43+
import org.eclipse.core.runtime.IProgressMonitor;
44+
import org.eclipse.core.runtime.IStatus;
45+
import org.eclipse.core.runtime.Status;
46+
import org.eclipse.emf.common.util.URI;
47+
import org.eclipse.emf.ecore.EObject;
48+
import org.eclipse.emf.ecore.resource.ResourceSet;
49+
import org.eclipse.jface.viewers.ISelection;
50+
import org.eclipse.jface.viewers.IStructuredSelection;
51+
import org.eclipse.ui.handlers.HandlerUtil;
52+
import org.eclipse.xtext.ui.resource.IResourceSetProvider;
53+
import org.omg.sysml.lang.sysml.Element;
54+
import org.omg.sysml.util.repository.ProjectDelta;
55+
import org.omg.sysml.util.repository.RepositoryContentFetcher;
56+
import org.omg.sysml.util.repository.RepositoryProject;
57+
import org.omg.sysml.util.traversal.Traversal;
58+
import org.omg.sysml.util.traversal.facade.impl.ElementIdProcessingFacade;
59+
60+
import com.google.inject.Inject;
61+
62+
public class PullRepositoryProject extends AbstractHandler {
63+
64+
private static final Set<String> FILE_EXTENSIONS = Set.of("sysml", "kerml", "sysmlx", "kermlx");
65+
66+
@Inject
67+
private IResourceSetProvider resourceSetProvider;
68+
69+
@Override
70+
public Object execute(ExecutionEvent event) throws ExecutionException {
71+
72+
ISelection selection = HandlerUtil.getCurrentSelection(event);
73+
74+
if (selection != null && selection instanceof IStructuredSelection) {
75+
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
76+
structuredSelection.stream()
77+
.filter(IProject.class::isInstance)
78+
.map(IProject.class::cast).findFirst().ifPresent(this::tryPullRemoteFor);;
79+
80+
}
81+
82+
return null;
83+
}
84+
85+
private void tryPullRemoteFor(IProject project) {
86+
WorkspaceJob job = new WorkspaceJob("Pulling from remote") {
87+
88+
@Override
89+
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
90+
91+
tryPullRemoteFor(project, monitor);
92+
return Status.OK_STATUS;
93+
}
94+
};
95+
96+
job.setUser(true);
97+
job.setRule(project.getWorkspace().getRoot());
98+
job.schedule();
99+
}
100+
101+
private void tryPullRemoteFor(IProject project, IProgressMonitor monitor) {
102+
try {
103+
IProject[] referencedProjects = project.getDescription().getReferencedProjects();
104+
Optional<IProject> libraryProject = Stream.of(referencedProjects).filter(rp -> rp.getName().contains("sysml.library")).findFirst();
105+
106+
if (libraryProject.isPresent()) {
107+
Properties properties = new Properties();
108+
IFile repositoryPropertiesFile = project.getFile(".settings/org.omg.sysml.remote.properties");
109+
110+
properties.load(repositoryPropertiesFile.getContents());
111+
112+
String repositoryUrl = properties.getProperty("base.url");
113+
String projectName = properties.getProperty("remote.projectId");
114+
String targetPath = project.getFullPath().toString();
115+
116+
Set<IFile> libraryResources = new HashSet<>();
117+
collectFiles(libraryProject.get(), libraryResources);
118+
119+
ResourceSet resourceSet = resourceSetProvider.get(project);
120+
loadResources(resourceSet, libraryProject.get(), libraryResources);
121+
122+
//collect ids from library
123+
ElementIdProcessingFacade idProcessingFacade = new ElementIdProcessingFacade();
124+
var traversal = new Traversal(idProcessingFacade, true);
125+
126+
resourceSet.getResources().forEach(res -> {
127+
if (!res.getContents().isEmpty()) {
128+
traversal.visit((Element) res.getContents().get(0));
129+
}
130+
});
131+
132+
Map<Object, EObject> uuidToElementMap = idProcessingFacade.getUUIDToElementMap();
133+
134+
RepositoryProject repositoryProject = new RepositoryProject(repositoryUrl, projectName);
135+
RepositoryContentFetcher repositoryFetcher = new RepositoryContentFetcher(repositoryProject, uuidToElementMap);
136+
ProjectDelta delta = repositoryFetcher.fetch();
137+
delta.save(resourceSet, targetPath);
138+
}
139+
} catch (IOException | CoreException e) {
140+
e.printStackTrace();
141+
}
142+
}
143+
144+
private static void loadResources(ResourceSet rs, IProject project, Collection<IFile> files) {
145+
146+
for (IFile file: files) {
147+
String projectRelativeString = file.getProjectRelativePath().toString();
148+
URI platformResourceUri = URI
149+
.createPlatformResourceURI("/" + project.getName() + "/" + projectRelativeString, true);
150+
rs.getResource(platformResourceUri, true);
151+
}
152+
}
153+
154+
private static void collectFiles(IContainer container, Collection<IFile> files) throws CoreException {
155+
IResource[] members = container.members();
156+
for (int i = 0; i < members.length; i++) {
157+
if (members[i] instanceof IContainer) {
158+
collectFiles((IContainer) members[i], files);
159+
} else if (members[i] instanceof IFile) {
160+
IFile file = (IFile) members[i];
161+
if (FILE_EXTENSIONS.contains(file.getFileExtension())) {
162+
files.add(file);
163+
}
164+
}
165+
}
166+
}
167+
}

org.omg.sysml.xtext/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Require-Bundle: org.eclipse.xtext,
2222
org.objectweb.asm;bundle-version="9.3.0";resolution:=optional,
2323
org.apache.commons.cli
2424
Export-Package: org.omg.sysml.sysmlx,
25+
org.omg.sysml.xmi,
2526
org.omg.sysml.xtext,
2627
org.omg.sysml.xtext.generator,
2728
org.omg.sysml.xtext.library,

org.omg.sysml.xtext/src/org/omg/sysml/xtext/util/SysMLRepositoryLoadUtil.java

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
*/
2323
package org.omg.sysml.xtext.util;
2424

25+
import java.io.File;
2526
import java.io.IOException;
26-
import java.util.Collections;
2727
import java.util.Map;
2828

2929
import org.apache.commons.cli.CommandLine;
@@ -32,13 +32,9 @@
3232
import org.apache.commons.cli.Option;
3333
import org.apache.commons.cli.Options;
3434
import org.apache.commons.cli.ParseException;
35-
import org.eclipse.emf.common.util.URI;
3635
import org.eclipse.emf.ecore.EObject;
37-
import org.eclipse.emf.ecore.resource.Resource;
3836
import org.eclipse.emf.ecore.resource.ResourceSet;
39-
import org.eclipse.xtext.resource.XtextResource;
4037
import org.omg.kerml.xtext.KerMLStandaloneSetup;
41-
import org.omg.kerml.xtext.linking.KerMLLazyLinkingResource;
4238
import org.omg.sysml.lang.sysml.Element;
4339
import org.omg.sysml.util.ElementUtil;
4440
import org.omg.sysml.util.SysMLUtil;
@@ -47,14 +43,18 @@
4743
import org.omg.sysml.util.repository.RepositoryProject;
4844
import org.omg.sysml.util.traversal.Traversal;
4945
import org.omg.sysml.util.traversal.facade.impl.ElementIdProcessingFacade;
46+
import org.omg.sysml.xmi.SysMLxStandaloneSetup;
5047
import org.omg.sysml.xtext.SysMLStandaloneSetup;
5148

5249
public class SysMLRepositoryLoadUtil extends SysMLUtil {
5350

54-
private static final String EXTENSION = "xmi";
55-
5651
public static void main(String[] args) throws ParseException {
5752
SysMLRepositoryLoadUtil sysMLRepositoryLoadUtil = createUsingArgs(args);
53+
54+
KerMLStandaloneSetup.doSetup();
55+
SysMLStandaloneSetup.doSetup();
56+
SysMLxStandaloneSetup.doSetup();
57+
5858
sysMLRepositoryLoadUtil.load();
5959
}
6060

@@ -80,25 +80,22 @@ public static SysMLRepositoryLoadUtil createUsingArgs(String... args) throws Par
8080
cli.hasOption(repositoryOption)? cli.getOptionValue(repositoryOption) : "http://localhost:9000",
8181
cli.getOptionValue(projectOption),
8282
cli.getOptionValue(targetOption),
83-
cli.getOptionValue(localLibrary)
83+
new File(cli.getOptionValue(localLibrary))
8484
);
8585
}
8686

8787
private final String repositoryURL;
8888
private final String projectName;
8989
private final String targetLocation;
90-
private final String localLibraryPath;
90+
private final File localLibraryPath;
9191

92-
public SysMLRepositoryLoadUtil(String repositoryURL, String projectName, String targetLocation, String localLibraryPath) {
92+
public SysMLRepositoryLoadUtil(String repositoryURL, String projectName, String targetLocation, File localLibraryPath) {
9393
super();
9494
this.repositoryURL = repositoryURL;
9595
this.projectName = projectName;
9696
this.targetLocation = targetLocation;
9797
this.localLibraryPath = localLibraryPath;
9898

99-
KerMLStandaloneSetup.doSetup();
100-
SysMLStandaloneSetup.doSetup();
101-
10299
addExtension(".sysml");
103100
addExtension(".kerml");
104101
}
@@ -128,21 +125,10 @@ public void load() {
128125
RepositoryContentFetcher repositoryFetcher = new RepositoryContentFetcher(repositoryProject, uuidToElementMap);
129126
ProjectDelta delta = repositoryFetcher.fetch();
130127

131-
var projectRoots = delta.getProjectRoots();
132-
128+
ResourceSet resourceSet = getResourceSet();
129+
133130
try {
134-
ResourceSet resourceSet = getResourceSet();
135-
136-
for (var root : projectRoots.keySet()) {
137-
var dto = projectRoots.get(root);
138-
Object object = dto.get("@id");
139-
URI fileURI = URI.createFileURI(String.format("%s/%s.%s", targetLocation, object.toString(), EXTENSION));
140-
Resource resource = resourceSet.createResource(fileURI);
141-
resource.getContents().add(root);
142-
System.out.println("Saving resource");
143-
resource.save(Collections.EMPTY_MAP);
144-
145-
}
131+
delta.save(resourceSet, targetLocation);
146132
} catch (IOException e) {
147133
e.printStackTrace();
148134
}

org.omg.sysml/src/org/omg/sysml/util/repository/ProjectDelta.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@
2121

2222
package org.omg.sysml.util.repository;
2323

24+
import java.io.IOException;
25+
import java.util.Collections;
2426
import java.util.Map;
2527

28+
import org.eclipse.emf.common.util.URI;
2629
import org.eclipse.emf.ecore.EObject;
30+
import org.eclipse.emf.ecore.resource.Resource;
31+
import org.eclipse.emf.ecore.resource.ResourceSet;
2732
import org.omg.sysml.model.Element;
33+
import org.omg.sysml.util.ElementUtil;
2834

2935
public class ProjectDelta {
36+
private static final Object EXTENSION = "sysmlx";
3037

3138
private final RepositoryProject remoteProject;
3239
private final Map<EObject, Element> projectRoots;
@@ -39,4 +46,16 @@ public ProjectDelta(RepositoryProject remoteProject, Map<EObject, Element> proje
3946
public Map<EObject, Element> getProjectRoots() {
4047
return projectRoots;
4148
}
49+
50+
public void save(ResourceSet resourceSet, String targetLocation) throws IOException {
51+
for (var root : projectRoots.keySet()) {
52+
var dto = projectRoots.get(root);
53+
Object object = dto.get("@id");
54+
URI fileURI = URI.createFileURI(String.format("%s/%s.%s", targetLocation, object.toString(), EXTENSION));
55+
Resource resource = resourceSet.createResource(fileURI);
56+
resource.getContents().add(root);
57+
ElementUtil.transformAll(resource, false);
58+
resource.save(Collections.EMPTY_MAP);
59+
}
60+
}
4261
}

org.omg.sysml/src/org/omg/sysml/util/repository/RepositoryContentFetcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ private void transformStructuralFeature(EObject langElement, Element remoteElem
209209
}
210210
}
211211
catch (Exception e) {
212-
e.printStackTrace();
212+
// e.printStackTrace();
213213
System.out.printf("Unable to set structural feature %s::%s %n", feature.getEContainingClass().getName(), feature.getName());
214214
}
215215
}

0 commit comments

Comments
 (0)