This repository was archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathmodel.coffee
More file actions
126 lines (101 loc) · 3.36 KB
/
model.coffee
File metadata and controls
126 lines (101 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
{Behavior, Subscriber, Emitter} = require 'emissary'
PropertyAccessors = require 'property-accessors'
Delegator = require 'delegato'
nextInstanceId = 1
module.exports =
class Model
Subscriber.includeInto(this)
Emitter.includeInto(this)
PropertyAccessors.includeInto(this)
Delegator.includeInto(this)
@resetNextInstanceId: -> nextInstanceId = 1
@properties: (args...) ->
if typeof args[0] is 'object'
@property name, defaultValue for name, defaultValue of args[0]
else
@property arg for arg in args
@property: (name, defaultValue) ->
@declaredProperties ?= {}
@declaredProperties[name] = defaultValue
@::accessor name,
get: -> @get(name)
set: (value) -> @set(name, value)
@::accessor "$#{name}",
get: -> @behavior(name)
@behavior: (name, definition) ->
@declaredBehaviors ?= {}
@declaredBehaviors[name] = definition
@::accessor name,
get: -> @behavior(name).getValue()
@::accessor "$#{name}",
get: -> @behavior(name)
@hasDeclaredProperty: (name) ->
@declaredProperties?.hasOwnProperty(name)
@hasDeclaredBehavior: (name) ->
@declaredBehaviors?.hasOwnProperty(name)
@evaluateDeclaredBehavior: (name, instance) ->
@declaredBehaviors[name].call(instance)
declaredPropertyValues: null
behaviors: null
alive: true
constructor: (params) ->
@assignId(params?.id)
for propertyName of @constructor.declaredProperties
if params?.hasOwnProperty(propertyName)
@set(propertyName, params[propertyName])
else
@setDefault(propertyName) unless @get(propertyName, true)?
assignId: (id) ->
@id ?= id ? nextInstanceId++
setDefault: (name) ->
defaultValue = @constructor.declaredProperties?[name]
defaultValue = defaultValue.call(this) if typeof defaultValue is 'function'
@set(name, defaultValue)
get: (name, suppressDefault) ->
if @constructor.hasDeclaredProperty(name)
@declaredPropertyValues ?= {}
@setDefault(name) unless suppressDefault or @declaredPropertyValues.hasOwnProperty(name)
@declaredPropertyValues[name]
else
@[name]
set: (name, value) ->
if typeof name is 'object'
properties = name
@set(name, value) for name, value of properties
properties
else
unless @get(name, true) is value
if @constructor.hasDeclaredProperty(name)
@declaredPropertyValues ?= {}
@declaredPropertyValues[name] = value
else
@[name] = value
@behaviors?[name]?.emitValue(value)
value
@::advisedAccessor 'id',
set: (id) -> nextInstanceId = id + 1 if id >= nextInstanceId
behavior: (name) ->
@behaviors ?= {}
if behavior = @behaviors[name]
behavior
else
if @constructor.hasDeclaredProperty(name)
@behaviors[name] = new Behavior(@get(name)).retain()
else if @constructor.hasDeclaredBehavior(name)
@behaviors[name] = @constructor.evaluateDeclaredBehavior(name, this).retain()
when: (signal, action) ->
@subscribe signal, (value) =>
if value
if typeof action is 'function'
action.call(this)
else
this[action]()
destroy: ->
return unless @isAlive()
@alive = false
@destroyed?()
@unsubscribe()
behavior.release() for name, behavior of @behaviors
@emit 'destroyed'
isAlive: -> @alive
isDestroyed: -> not @isAlive()