Uploaded image for project: 'App Framework'
  1. App Framework
  2. AF-10

Introduce generic interfaces to represent Extension and ExtensionPoint, and refactor AppDescriptor

    XMLWordPrintable

    Details

    • Type: New Feature
    • Status: Closed
    • Priority: Must
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0
    • Complexity:
      High

      Description

      Originally I defined AppDescriptor and AppFactory classes in the AppFramework module, and later I defined TaskDescriptor and TaskFactory interfaces in the EMR module, as a later iteration on a similar idea. (A key improvement is that the TaskDescriptor methods take an EmrContext argument, which is necessary for interesting implementations of the isAvailable method, for example.)

      There's actually a generic idea that both App and Task both extend. For lack of a better term, we're calling this Extension.

      We need to introduce interfaces in the App Framework module like:

      interface ExtensionPoint {
          String getId(); // e.g. "org.openmrs.homepage.app"
          Class<? extends Extension> getRequiredType(); // e.g. LinkExtension.class
      }
      
      interface Extension {
          String getTargetExtensionPoint(); // e.g. "org.openmrs.homepage.app"
      }
      
      
      interface ExtensionService extends OpenmrsService {
          List<Extension> getAvailableExtensionsByPointId(AppFrameworkContext context, String extensionPointId); // replace existing calls to getAvailableApps with getAvailableExtensionsByPointId(context, "org.openmrs.homepage.app")
      
          List<Extension> getAllExtensions();
      
          List<ExtensionPoint> getAllExtensionPoints();
      
          // maybe
          <Ext extends Extension> List<Ext> getAvailableExtensionsByClass(AppFrameworkContext context, Class<Ext> class);
      }
      
      // gives us a flexible way to let the webapp/framework pass information that is needed to determine whether certain extensions are available or not based on things like "which user is logged in", "which roles does the authenticated user have", "what is the session location", "what browser/device is the user on"
      class AppFrameworkContext { // or interface?
          UserContext getUserContext();
          Object getProperty(String propertyName);
          void setProperty(String propertyName, Object propertyValue);
      }
      
      class LinkExtension implements Extension {
          String url;
          String label;
          String icon;
      }
      

      I realize that as-written these may not support the client-side model well, so let's modify as necessary.

      Later we'll want ways to let modules produce multiple extensions and extension points dynamically

      interface ExtensionPointFactory {
          List<ExtensionPoint> getExtensionPoints();
      }
      interface ExtensionFactory {
          List<Extension> getExtensions();
      }
      

      I noticed that I've actually written implementations of a lot of this a few years back. These live here, but they're just illustrative, not intended to be used verbatim.

      In the process of doing this we should remove some of the overly-optimistic methods I put on AppDescriptor (e.g. startApp, endApp) so we start off with a very simple idea of an App, and add onto this through the work we're doing here.

        Attachments

          Activity

            People

            Assignee:
            nutsiepully Pulkit Bhuwalka
            Reporter:
            darius Darius Jazayeri
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: