Skip to content

Conversation

TheKorpos
Copy link
Contributor

This PR introduces a new programmatic API that provides an easy setup for the language infrastructure (inlcuding reading the standard library) and interfaces for model reading/processing.

Example usages

SysMLAccess access = SysMLAccess.createFullyFeatured("path_to_lib"); //init the lang. infrastructure and set library path
access.loadLibrary(); //load the library
access.parse("myres.sysml", "package A { }"); //parse a string and put it in a resource
Element element = access.resolve("$::A"); //resolve and element by qualified name

with REST access

SysMLAccess access = SysMLAccess.createFullyFeaturedWithAPIAccess("path_to_lib", "http://localhost:9000");
access.loadLibrary();
List<Resource> loadedResources = access.getAPIAccess().load(new APIProjectDescriptor().projectName("myProject"));

Changes

Added

  • SysMLAccess: main interface to interract with the language infrastructure

    • extends SysMLUtil
    • library load
    • parsing string input
    • parsing files
    • resolving by qn
  • SysMLAPIAccess: simplified interfaces for publish/load

    • loading
    • publishing
    • listing projects from repository
  • SysMLParseResult: wrapper class for parsing/validation issues

  • SysMLAccess.Builder: builder for SysMLAccess instaces (mainly for future extendability and configuration)

  • SysMLAccessTest: test cases for the new API

Modified

  • SysMLUtil
    • revised handing folders and file extensions
    • pushed some exception handling to the user side (e.g IOExceptions)
    • moved static helpers from SysMLInteractiveUtil (these are mostly for printing parts of the model in a human readable format)
  • SysMLInteractive
    • now extends SysMLAccess. It's interfaces remain the same but there are some implementation changes (e.g moving functionality up to SysMLAccess)
  • comand line utils:
    • added added try/catch blocks for newly thrown exceptions

Removed

  • SysMLInteractiveUtil (moved static helpers to SysMLUtil)

@TheKorpos TheKorpos requested a review from seidewitz September 4, 2025 12:35
@himi
Copy link
Member

himi commented Sep 4, 2025

I noticed SysMLAccess.build() and SysMLInteractive.createInstance() overlaps in many ways. Can we make createInstance() use build()? Also don't we need to call
KerMLxStandaloneSetup.doSetup();
SysMLxStandaloneSetup.doSetup();
in build()?

So, for extension purpose, I think we change build() and createInstance() by using generics. For example,

     public static <T extends SysMLAccess> T build(ISetup setup, java.lang.Class<T> cls) {
               Injector injector = setup.createInjectorAndDoEMFRegistration();	
               T access = injector.getInstance(cis);
               return access;
       }

        public static SysMLAccess build() {
                 return build(new SysMLStandaloneSetup(), SysMLAccess.class);
       }

I can propose a commit to use this mechanism. So SysMLInteractive().createInstance() can call build(setup, SysMLInteractive.class) to create a SysMLInteractive instance.

@himi
Copy link
Member

himi commented Sep 4, 2025

Actually, we should use the same name to create an instance. I prefer createInstance() to build().. I slightly changed my mind, if we use builder pattern, build() is a natural name. One issue is that why not using the same pattern for SysMLInteractive? But SysMLInteractive is used by Jupyter kernel and I think we should keep these names if we do not use builder pattern for SysMLInteractive.

Also we can put setup and cls into a builder instance. In my opinion, we can put setup in a builder but I want to put cls in the argument of build() because it can be regarded as a special configuration and also only one argument is not so complicated.

@TheKorpos
Copy link
Contributor Author

@himi
We wanted to mostly keep SysMLInteractive as it is for now. But I also didn't want to end up with a bunch of code duplications so I ended up 'inserting' SysMLAccess between SysMLUtil and SysMLInteractive and pushing some of the logic from interactive to access.
Ideally, SysMLInteractive should encapsulate an isntance of SysMLAccess that uses the StrictShadowingResourceDescriptionData. SysMLInteractive should really just handle the user input and then call the access instance. At least that's what I think. But we wanted to figure out interactive at a later time.

As for the builder. I'm not entierly sure whether we even want it or not. My intention was to have some really easy way of setting most things up: createFullyFeatured, createFullyFeaturedWithAPIAccess. And have something that provides some level of customization but I haven't really figured out what would be best on that end.

KerMLxStandaloneSetup.doSetup();
SysMLxStandaloneSetup.doSetup();

You only need these if you want to work with XMI (.kermlx, .sysmlx) and/or use the REST API. createFullyFeatured and createFullyFeaturedWithAPIAccess sets these up by default but I also wanted a way not to set these up. The builder doesn't set these up by default. To explicitly set these up, the builder has .xmiSupport() but setting the api base path will also call these on build()

@himi
Copy link
Member

himi commented Sep 4, 2025

I see your point. However, it's really already quite complicated and duplicated in the current initialization. I believe now is the best timing to clean them up (I'm pretty sure we will not do it in the future). At least, SysMLInteractive.createInstance() should use Builder.build().

In addition, we want to extend SysMLInteractive with our own Setup. I hope SysMLAccess/SysMLInteractive flexibly allows such kind of extension use case, and I believe, SysMLInteractive is exactly a good extension case for SysMLAccess.

@ujhelyiz
Copy link
Contributor

ujhelyiz commented Sep 5, 2025

Where to call the doSetup is quite an interesting question, for two reasons:

  1. These methods should be called exactly once. If called multiple times, e.g., an application wants to start multiple SysMLAccess instances for separation purposes, it could cause tricky surprises.
  2. If you want the setups to be customizable, it might be better for this service not to call it, as in that case, the replacement is trivial.

@himi
Copy link
Member

himi commented Sep 5, 2025

@ujhelyiz
Agreed. I want to encapsulate everything into ISetup instance but it's actually not. I think we should encapsulate everything related to static initializers in build() method only. Anyway, I want to use extend SysMLAccess or SysMLInteractive for extension with my own ISetup.

@seidewitz seidewitz changed the title ST6RI-683 Programmatic interface ST6RI-683 Provide a better programmatic interface Sep 10, 2025
@seidewitz seidewitz self-assigned this Sep 22, 2025
@seidewitz seidewitz added this to the 2025-08 milestone Sep 22, 2025
@seidewitz seidewitz marked this pull request as draft September 30, 2025 21:50
@seidewitz seidewitz modified the milestones: 2025-09, 2025-10 Oct 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants