class Role
  constructor: (spec, entityInterface)->
    @validateSpec(spec)
    @spec = spec## 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 = specentityInterface 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 @entityInterfacecheck 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 ActorAn 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)