Adding smart references using transformation menus

This post will follow a user friendly way of creating nodes, adding them to a location of our choice and referring to them from a smart reference, from the transformation menu of a smart reference.

transformation menu example

Rationale

Having references is helpful in a lot of ways. Instead of creating and storing data every time you need it you can store it in one place and access it later from various locations and manipulate it. This saves memory and computing time since we will mostly pass on addresses instead of the entire values of a variable. Smart references are as transparent as they can - you can see all nodes you can refer to through the completion menu as if you are adding a node of the concept.

An issue pops up when you actually want to add a new entry to the list of referred items. Then you would have to manually go to the list and add the entry yourself which may be harder than expected if the project is large.

Overview

You can find the example project we will see here at F1res GitHub page.

The idea of the sample project is to have a store for words and one or many thesauri that can define synonyms or if the language is extended in the future - different types of dictionaries.

We have a language called Dictionary that can store nouns into WordStores and refer to them in Thesaurus root nodes.

project structure
Figure 1. Project Structure

NounWord implements the INamedConcept interface.

250
Figure 2. Noun word concept

Its reference concept NounWordRef has an originalWord reference of cardinality [1] to a NounWord concept.

250
Figure 3. Noun word reference concept

The WordStore contains NounWords and the Thesaurus contains Definitions that have a reference to the noun word it’s going to assign synonyms to and a list of noun word references for the synonyms. The Thesaurus also contains a reference to the wordStore it’s going to get words from.

250
Figure 4. Word store concept
260
Figure 5. Thesaurus concept
250
Figure 6. Synonym concept

With this setup if we wanted to add new words we have to go to the WordStore and add them manually. Then we have to go back to the Thesaurus and use them.

We can ease this process by adding the possibility to directly add entries to the wordStore from the completion menu of the smart reference. We are going to use the transformation menu for this solution.

We will add a Transformation Menu to the NounWordRef concept. In this transformation menu we will create a completion section that has two actions, because if it has only one the autocomplete will execute it immediately and fill our wordStore with nonsense comprised of every letter of a word until we have finished.

example one action
Figure 7. Example of word store with one action
A transformation menu allows us to transform the current node in whatever direction we want. With it we can manipulate the node in several ways - completion, context assistant, side transform. We can overwrite the default or define additional entries to these sections.
The completion section extends the code completion tool (ctrl+space). It allows for a fluid access to various menus of sub/super-concepts or user defined actions without interrupting the flow of writing code.

In these actions we create a new noun node, add it to the wordStore and set our nodes reference to it.

Transformation menu checklist

First we will create a runtime solution with a helper method that will hold the logic of the transformation menu. It is generally better to hold more complex logic in separate helper classes.

  • Create a language runtime solution.

  • Add a model for the editor of the language with the following dependencies and used languages.

helper class dep
Figure 8. Word store concept
helper class used
Figure 9. Dictionary concept
  • Create a helper class.

  • Add one class variable that is of type node<wordStore>.

  • Add one static final class variables of type string with value "Add new concept to store.".

  • Add another static final class variables of type string with value "Do not use!".

  • Add the constructor to the class which assigns the wordStore to an external wordStore.

  • Add one method that checks if a string, given in the parameters, is empty or if a noun that matches it exists.

  • Add one method that creates a new noun, from a string parameter, adds it to the word store and assigns it to a NounWordRef, also from a parameter.
    We do that by creating a new word and assigning it’s name to be the pattern by using light quotation (ctrl+space + "<light quotation>").
    Then adding the new word to the list of the wordStore, and finally assigning the reference of our parameter NounWordRef to the newly created word.

helper class
Figure 10. Transformation Menu Helper class
  • Create a transformation menu for the NounWordRef node.

  • Add a completion section.

  • The default reference menu for the originalWord reference has to be included so the existing words will still be listed in the menu as possible reference targets.

  • Create a group, because we want to use variables. In this group do the following:

    • In the variables section add one variable that points to the wordStore root node so we can add new nodes to it.

    • In the variables section add another variable that is the helper class.
      It will assist with the logic of the transformation menu.

    • Add one action with the following items:

      • In the text section return the pattern variable.
        The pattern variable is what the user has written in the editor.

      • In the can execute section set conditions for the execution of the action.
        Use the helper method to check if the pattern variable is empty or if the word exists in the wordStore.

      • In the execute method call the addNewNoun helper method and pass the pattern and node variables to it.

      • Give the action a description text - use the constant we defined earlier in the helper method. In this case the ADD_NEW_NOUN string.

    • Add a second action with the following items:

      • In the text section return the pattern variable.
        Because otherwise the code won’t compile.

      • In the can execute section use the helper method checkWordExists to set a condition for the execution of the action.
        This is done to avoid having this item show up when it shouldn’t.

      • Leave the execute section empty so we do not confuse the user.

      • Add a description text - use the other constant we defined earlier in the helper method - the DO_NOT_USE_ITEM.

We could emphasize more that the second action is not important by adding a completion styling to our transformation menu that sets the strikeout flag to an item of the menu. This is completely visual and is not necessary for the example to work.
completion styling
Figure 11. Example of completion styling.
noun word ref transformation menu
Figure 12. Noun reference transformation menu
transformation menu example
Figure 13. Example of the transformation menu

About Atanas Marchev

I am a Junior Model Driven Engineer at F1RE. I started my journey with F1RE in December 2021. I’ve worked with many aspects of programming and this way of development seems very interesting. Just the thought alone of the way one has to extract basic concepts out of complex ideas and structures seems challenging enough to make your head spin.

You can contact me at atanas@f1re.io.