1 2 Previous Next 28 Replies Latest reply on Jun 5, 2012 2:06 PM by rbattenfeld

    SHRINKDESC-21 Prototyping - Read-only Views

    alrubinger

      The other day in #jbosstesting IRC a few of us discussed SHRINKDESC-21 and adding a "read-only" mode to SWD.

       

      Ralf has implemented a POC (which is now in upstream/SHRINKDESC-21), and I'd made some notes regarding its design on the pull request[1].  We'd then determined that there should be a relationship between the read-only and mutable views such that the user could switch from one to the other; this isn't a security feature perse to prevent unauthorized state changes, but more a way of guarding against accidental ones and clearly denoting which calls are safe for read-only operations.

       

      In chat we'd together agreed that this construct should be possible:

       

      WebAppDescriptor readonlyWebapp = Descriptors.importFrom(File); // Read-only
      WebAppMutableDescriptor mutableWebapp = (WebAppMutableDescriptor) readonlyWebapp; // Cast to get mutable operations
      

       

      Aslak correctly raised the point that we also have to take into account mutable operations on transitive relationships, for instance:

       

      List<FilterType> readonlyFilterTypes = readonlyWebapp.getAllFilter(); 
      List<FilterMutableType> mutableFilterTypes = mutableWebapp.getAllFilter();
      

       

      I noted that a way we could handle this would be to take advantage of covarient return, meaning really:

       

      interface WebAppDescriptorBase<FILTERTYPE extends FilterTypeBase<FILTERTYPE, WEBAPPDESCRIPTORTYPE>, WEBAPPDESCRIPTORTYPE extends WebAppDescriptorBase<FILTERTYPE, WEBAPPDESCRIPTORTYPE>> {
      
        List<FILTERTYPE> getAllFilter();
      
      }
      

       

      Don't look at me, man; Java's generics support is really verbose.  And we can't leave it up to the USER to supply those ugly generic parameters, so we have to close the generic context and provide:

       

      public interface WebAppDescriptor extends WebAppDescriptorBase<FilterType, WebAppDescriptor> {}
      

       

      ...and:

       

      public interface WebAppMutableDescriptor extends WebAppDescriptorBase<FilterMutableType, WebAppMutableDescriptor> {}
      

       

      Cool, right?

       

      Not really; because at this point WebAppDescriptor is no longer a parent of WebAppMutableDescriptor, so you can't directly cast from one to the next.  The only way to do that is to show the user the common superclass, the base, with all the generic parameters in place. 

       

      Again, don't blame me.  This is how Java handles generics.  Even though WebAppDescriptor and WebAppMutableDescriptor are equivalent at runtime because the compiler drops the generics when generating bytecode, the hierarchy is broken and hence not castable.

       

      So I'll instead propose this:

       

      1) We introduce two new interfaces:

       

      interface Immutable<MUTABLETYPE extends Mutable> {
        MUTABLETYPE toMutable();
      }
      

       

      interface Mutable<IMMUTABLETYPE extends Immutable> {
        IMMUTABLETYPE toImmutable();
      }
      

       

      2) We compose by appling as such:

       

      public interface WebAppDescriptor extends WebAppDescriptorBase<FilterType, WebAppDescriptor>, Immutable<WebAppMutableDescriptor> {}
      

       

      public interface WebAppDescriptor extends WebAppDescriptorBase<FilterType, WebAppDescriptor>, Mutable<WebAppDescriptor> {}
      

       

      3) We switch between the two like this:

       

      WebAppMutableDescriptor mutableWebapp = readonlyWebapp.toMutable();
      WebAppDescriptor roundtrip = mutableWebapp.toImmutable();
      

       

      In this way we have essentially two views, much like ShrinkWrap has N views via the "Assignable" interface.

       

      WDYT?

       

      [1] https://github.com/shrinkwrap/descriptors/pull/57

        1 2 Previous Next