• Jump To … +
    server.coffee src/actionknob.coffee src/autosem.coffee src/bitbucket_kba.coffee src/browserlog.coffee src/datareduction.coffee src/dci.coffee src/dciknob.coffee src/deeseeeye.coffee src/dnd.coffee src/doof.coffee src/formurla-mngr.coffee src/fractalpanel.coffee src/fractalpanel_test.coffee src/front.coffee src/ingestor.coffee src/kbabitbucket.coffee src/knobctrl.coffee src/lib_test.coffee src/nanoclock.coffee src/noodb.coffee src/noodbabstract.coffee src/noodbbrowser.coffee src/noodbbrowser_test.coffee src/noodbsec.coffee src/noorauth.coffee src/noorplugin.coffee src/noorquery.coffee src/noorvm.coffee src/noorwrite.coffee src/quadparser.coffee src/quadparsern3.coffee src/rbac.coffee src/reactor.coffee src/rebase.coffee src/rsrcidx.coffee src/sandboxactions.coffee src/screen_ctx.coffee src/spogi.coffee src/tabular_widget.coffee src/visctrl.coffee src/voicesknob.coffee src/whowhen.coffee src/xsd2native.coffee
  • dci.coffee

  • ¶

    ## dci forked from https://github.com/brokenseal/eunomia/blob/master/src/eunomia.coffee version 0.0.1

    Data, Context, Interaction (DCI)

    see http://en.wikipedia.org/wiki/Data,_context_and_interaction http://www.artima.com/articles/dci_vision.html https://dzone.com/articles/implementing-dci-qi4j http://www.amazon.ca/Lean-Architecture-Agile-Software-Development/dp/0470684208/ https://github.com/amolenaar/roles/blob/master/example.py https://github.com/shamus/javascript-dci/blob/master/examples/frontloading.js

  • ¶

    ##

    class Role
      constructor: (spec, entityInterface)->
        @validateSpec(spec)
        @spec = spec
  • ¶

    entityInterface is a non mandatory interface to which entities need to comply to

        @entityInterface = entityInterface
    
      validateSpec: (spec)->
  • ¶

    a spec represents the role’s methods, need to contain only methods and no state

        for name of spec
          if not (spec[name] instanceof Function)
            throw new Error('Given spec is not accepted')
    
      validateInterfaceAgainst: (entity)->
        if @entityInterface
  • ¶

    check that the given entity complies to the previously given interface

          for name of @entityInterface
            obj = entity[name]
            klass = @entityInterface[name]
    
            if obj instanceof klass or toString.call(obj) is "[object " + klass.name + "]"
              continue
    
            throw new Error("Given entity does not comply to the role's needed interface,
                            attribute missing: `" + name + "` of type " + @entityInterface[name])
    
      applyTo: (entity)->
        @validateInterfaceAgainst(entity)
        return new Actor(@, entity)
    
    
    class Actor
  • ¶

    An actor is a role proxy, it exposes the same interface as the role specification but will apply its methods to the given entity. This way, the original entity object is left pristine and can easily impersonate other roles at the same time without other roles interfering with each other.

      constructor: (role, entity)->
        @entity = entity
        @role = role
    
        for name of @role.spec
          @[name] = @role.spec[name].bind(@entity)
    
    
    useCaseFactory = (roles, method)->
      return (entities)->
  • ¶

    create the actors the use case will manage

        actors = {}
        for name of entities
          actors[name] = roles[name].applyTo(entities[name])
    
        return method.call(null, actors)
    
    
    (exports ? this).context = (roles, useCases, formurlaManager)->
  • ¶

    validate roles

      for name of roles
        if not (roles[name] instanceof Role)
          throw new Error("Roles can only be instances of Role")
    
      if Object.keys(useCases).length is 0
        throw new Error('Context must be able to enact at least one use case')
    
      if formurlaManager?
        roles.formurlaManager = new Role
          get: () -> @  # the intention is to return the formurlaManager itself
          getNoodb: () -> @noodb  # the intention is to return the formurlaManager itself
          getRootPanel: () -> @rootPanel
    
      useCasesProxies = {}
      for name of useCases
        useCasesProxies[name] = useCaseFactory(roles, useCases[name])
    
      return useCasesProxies
    
    
    (exports ? this).role = (roleSpec, entityInterface)->
      return new Role(roleSpec, entityInterface)