summaryrefslogtreecommitdiffstats
path: root/coffee/lib/services/model.coffee
blob: a1316e3bb41dcf88e0d27e3f1bcecfad288fc2ab (plain)
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
127
128
129
130
131
###
# ownCloud
#
# @author Bernhard Posselt
# Copyright (c) 2012 - Bernhard Posselt <nukeawhale@gmail.com>
#
# This file is licensed under the Affero General Public License version 3 or later.
# See the COPYING-README file
#
###

angular.module('OC').factory '_Model', ->

	# Parent model: inherit your model from this object
	class Model

		constructor: ->
			@foreignKeys = {}
			@data = []
			@ids = {}


		handle: (data) ->
			if data['create'] != undefined
				for item in data['create']
					@create(item)

			if data['update'] != undefined
				for item in data['update']
					@update(item)

			if data['delete'] != undefined
				for item in data['delete']
					@delete(item)


		# @brief add a new foreign key name which caches data by foreign key
		# @param string name: the name of the foreign key property on the object
		# Foreign keys are caching items in a structure like
		# name -> id -> [item1, item2]
		hasForeignKey: (name) ->
			@foreignKeys[name] = {}


		# @brief adds a new object to the dataset
		# @param object data: the data that we want to store
		create: (data) ->
			if @ids[data.id] != undefined
				@update(data)
			else
				@data.push(data)
				@ids[data.id] = data

				# fill indizes of foreign keys
				for name, ids of @foreignKeys
					id = data[name]
					@foreignKeys[name][id] or= []
					@foreignKeys[name][id].push(data)


		# @brief updates an existing item, the id must not change
		# @param object item: the item which should be updated
		update: (item) ->
			currentItem = @ids[item.id]
			for key, value of item
				# if the foreignkey changed, we need to update the cache
				if @foreignKeys[key] != undefined
					if value != currentItem[key]
						@_updateForeignKeyCache(key, currentItem, item)
				if key != 'id'
					currentItem[key] = value


		delete: (item) ->
			if @getById(item.id) != undefined
				@removeById(item.id)


		_updateForeignKeyCache: (name, currentItem, toItem) ->
			fromValue = currentItem[name]
			toValue = toItem[name]
			foreignKeyItems = @foreignKeys[name][fromValue]
			@_removeForeignKeyCacheItem(foreignKeyItems, currentItem)
			@foreignKeys[name][toValue].push(item)


		_removeForeignKeyCacheItem: (foreignKeyItems, item) ->
			for fkItem, index in foreignKeyItems
				if fkItem.id == id
					@foreignKeys[key][item[key]].splice(index, 1)


		# @brief removes an object
		# @param int id: the id of the object
		removeById: (id) ->
			item = @getById(id)
			
			# remove from foreign key cache
			for key, ids of @foreignKeys
				foreignKeyItems = ids[item[key]]
				@_removeForeignKeyCacheItem(foreignKeyItems, item)

			# remove from array
			for item, index in @data
				if item.id == id
					@data.splice(index, 1)

			delete @ids[id]


		# @brief returns a data object by its id
		# @param int id: the id of the object that we want to fetch
		getById: (id) ->
			return @ids[id]


		# @brief returns all stored data objects
		getAll: ->
			return @data


		# @brief access the foreign key cache
		# @param string foreignKeyName: the name of the foreign key that we want to
		#                               look up
		# @param string foreignKeyId: the id from that foreign key that we want to
		#                             get
		getAllOfForeignKeyWithId: (foreignKeyName, foreignKeyId) ->
			return @foreignKeys[foreignKeyName][foreignKeyId]


	return Model