     references = {}
     json_events = []
     for event in events
+
       if event.document != @
         console.log("Cannot create a patch using events from a different document, event had ", event.document, " we are ", @)
         throw new Error("Cannot create a patch using events from a different document")
-      if event instanceof ModelChangedEvent
-        if event.attr == 'id'
-          console.log("'id' field is immutable and should never be in a ModelChangedEvent ", event)
-          throw new Error("'id' field should never change, whatever code just set it is wrong")
-        value = event.new_
-        value_json = HasProps._value_to_json('new_', value, event.model)
-        value_refs = {}
-        HasProps._value_record_references(value, value_refs, true) # true = recurse
-
-        if event.model.id of value_refs and event.model != value
-          # we know we don't want a whole new copy of the obj we're patching
-          # unless it's also the value itself
-          delete value_refs[event.model.id]
-        for id of value_refs
-          references[id] = value_refs[id]
-
-        json_event = {
-          'kind' : 'ModelChanged',
-          'model' : event.model.ref(),
-          'attr' : event.attr,
-          'new' : value_json
-        }
-
-        json_events.push(json_event)
-      else if event instanceof RootAddedEvent
-        HasProps._value_record_references(event.model, references, true)
-        json_event = {
-          'kind' : 'RootAdded',
-          'model' : event.model.ref()
-        }
-        json_events.push(json_event)
-      else if event instanceof RootRemovedEvent
-        json_event = {
-          'kind' : 'RootRemoved',
-          'model' : event.model.ref()
-        }
-        json_events.push(json_event)
-      else if event instanceof TitleChangedEvent
-        json_event = {
-          'kind' : 'TitleChanged',
-          'title' : event.title
-        }
-        json_events.push(json_event)
-
-    {
-      'events' : json_events,
-      'references' : Document._references_json(_.values(references))
-    }
+
+      json_events.push(event.json(references))
+
+    result =
+      events: json_events,
+      references: Document._references_json(_.values(references))
 
   apply_json_patch_string: (patch) ->
     @apply_json_patch(JSON.parse(patch))

    for r in @_roots
      root_ids.push(r.id)

    root_references =
      for k, v of @_all_models
        v

    {
      'title' : @_title

class ModelChangedEvent extends DocumentChangedEvent
  constructor : (@document, @model, @attr, @old, @new_) ->
    super @document
  json : (references) ->

    if @attr == 'id'
      console.log("'id' field is immutable and should never be in a ModelChangedEvent ", @)
      throw new Error("'id' field should never change, whatever code just set it is wrong")

    value = @new_
    value_json = HasProps._value_to_json('new_', value, @model)

    value_refs = {}
    HasProps._value_record_references(value, value_refs, true) # true = recurse

    if @model.id of value_refs and @model != value
      # we know we don't want a whole new copy of the obj we're
      # patching unless it's also the value itself
      delete value_refs[@model.id]

    for id of value_refs
      references[id] = value_refs[id]

    {
      'kind' : 'ModelChanged',
      'model' : @model.ref(),
      'attr' : @attr,
      'new' : value_json
    }

class TitleChangedEvent extends DocumentChangedEvent
  constructor : (@document, @title) ->
    super @document
  json : (references) ->
    {
      'kind' : 'TitleChanged',
      'title' : @title
    }

class RootAddedEvent extends DocumentChangedEvent
  constructor : (@document, @model) ->
    super @document
  json : (references) ->
    HasProps._value_record_references(@model, references, true)
    {
      'kind' : 'RootAdded',
      'model' : @model.ref()
    }

class RootRemovedEvent extends DocumentChangedEvent
  constructor : (@document, @model) ->
    super @document
  json : (references) ->
    {
      'kind' : 'RootRemoved',
      'model' : @model.ref()
    }

DEFAULT_TITLE = "Bokeh Application"

