1 | // Copyright 2004-2007 Jean-Francois Poilpret |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package net.sourceforge.hiveboard.model; |
16 | |
17 | import java.util.HashMap; |
18 | import java.util.Map; |
19 | |
20 | import net.sourceforge.hiveboard.Board; |
21 | import net.sourceforge.hiveboard.Event; |
22 | import net.sourceforge.hiveboard.EventType; |
23 | import net.sourceforge.hiveboard.event.ConstraintEventFilter; |
24 | import net.sourceforge.hiveboard.event.Constraints; |
25 | import net.sourceforge.hiveboard.event.EventsPriorities; |
26 | import net.sourceforge.hiveboard.event.PersistentDeferredConsumer; |
27 | import net.sourceforge.hiveboard.main.IdentityHolder; |
28 | import net.sourceforge.hiveevents.Channel; |
29 | import net.sourceforge.hiveevents.Filter; |
30 | |
31 | /** |
32 | * Service acting as a memory repository of all active Whiteboards in the system. |
33 | * <p> |
34 | * This service must use the singleton service model. |
35 | * |
36 | * @author Jean-Francois Poilpret |
37 | */ |
38 | public class BoardRepositoryImpl implements BoardRepository |
39 | { |
40 | public BoardRepositoryImpl(Channel<Event> eventChannel, IdentityHolder holder) |
41 | { |
42 | _identity = holder; |
43 | |
44 | // Add events listeners |
45 | int priority = EventsPriorities.BOARD_REPOSITORY_UPDATE; |
46 | String constraint = Constraints.eventType( EventType.EVT_CREATE_BOARD, |
47 | EventType.EVT_MODIFY_BOARD); |
48 | Filter<Event> filter = new ConstraintEventFilter(constraint); |
49 | PersistentDeferredConsumer consumer = new PersistentDeferredConsumer() |
50 | { |
51 | @Override protected void pushEvent(Event event) |
52 | { |
53 | int idBoard = event.getWhere(); |
54 | Board board = event.getBoard(); |
55 | if (board.getParticipants().contains(_identity.getId())) |
56 | { |
57 | Board oldBoard = _boards.get(idBoard); |
58 | if (oldBoard == null) |
59 | { |
60 | _boards.put(idBoard, board); |
61 | } |
62 | else |
63 | { |
64 | // Board already in repository, update it but do not replace it! |
65 | Board.copy(board, oldBoard, false); |
66 | } |
67 | } |
68 | else |
69 | { |
70 | // self has been removed from the board |
71 | _boards.remove(idBoard); |
72 | } |
73 | } |
74 | }; |
75 | eventChannel.registerPushConsumer(priority, filter, consumer); |
76 | |
77 | constraint = Constraints.eventType(EventType.EVT_DESTROY_BOARD); |
78 | filter = new ConstraintEventFilter(constraint); |
79 | consumer = new PersistentDeferredConsumer() |
80 | { |
81 | @Override protected void pushEvent(Event event) |
82 | { |
83 | _boards.remove(event.getWhere()); |
84 | } |
85 | }; |
86 | eventChannel.registerPushConsumer(priority, filter, consumer); |
87 | |
88 | constraint = Constraints.eventType(EventType.EVT_JOIN_BOARD); |
89 | filter = new ConstraintEventFilter(constraint); |
90 | consumer = new PersistentDeferredConsumer() |
91 | { |
92 | @Override protected void pushEvent(Event event) |
93 | { |
94 | Board board = getBoard(event.getWhere()); |
95 | board.getPresents().add(event.getWho()); |
96 | } |
97 | }; |
98 | eventChannel.registerPushConsumer(priority, filter, consumer); |
99 | |
100 | constraint = Constraints.eventType(EventType.EVT_LEAVE_BOARD); |
101 | filter = new ConstraintEventFilter(constraint); |
102 | consumer = new PersistentDeferredConsumer() |
103 | { |
104 | @Override protected void pushEvent(Event event) |
105 | { |
106 | Board board = getBoard(event.getWhere()); |
107 | board.getPresents().remove(event.getWho()); |
108 | } |
109 | }; |
110 | eventChannel.registerPushConsumer(priority, filter, consumer); |
111 | |
112 | constraint = Constraints.eventType(EventType.EVT_BOARD_ADD_PARTICIPANT); |
113 | filter = new ConstraintEventFilter(constraint); |
114 | consumer = new PersistentDeferredConsumer() |
115 | { |
116 | @Override protected void pushEvent(Event event) |
117 | { |
118 | if (event.getBoard() != null) |
119 | { |
120 | // Actually self is the new participant => new board in repository |
121 | _boards.put(event.getWhere(), event.getBoard()); |
122 | } |
123 | else |
124 | { |
125 | Board board = getBoard(event.getWhere()); |
126 | board.getParticipants().add(event.getWho()); |
127 | } |
128 | } |
129 | }; |
130 | eventChannel.registerPushConsumer(priority, filter, consumer); |
131 | |
132 | constraint = Constraints.eventType(EventType.EVT_BOARD_DEL_PARTICIPANT); |
133 | filter = new ConstraintEventFilter(constraint); |
134 | consumer = new PersistentDeferredConsumer() |
135 | { |
136 | @Override protected void pushEvent(Event event) |
137 | { |
138 | if (event.getWho() == _identity.getId()) |
139 | { |
140 | // Deleted participant is self |
141 | _boards.remove(event.getWhere()); |
142 | } |
143 | else |
144 | { |
145 | Board board = getBoard(event.getWhere()); |
146 | int who = event.getWho(); |
147 | board.getParticipants().remove(who); |
148 | // Remove from presents (just in case) |
149 | board.getPresents().remove(who); |
150 | // If that participant was also writer, then reset writer for the board |
151 | if (board.getWriter() == who) |
152 | { |
153 | board.setWriter(0); |
154 | } |
155 | } |
156 | } |
157 | }; |
158 | eventChannel.registerPushConsumer(priority, filter, consumer); |
159 | |
160 | constraint = Constraints.eventType(EventType.EVT_GIVE_TOKEN); |
161 | filter = new ConstraintEventFilter(constraint); |
162 | consumer = new PersistentDeferredConsumer() |
163 | { |
164 | @Override protected void pushEvent(Event event) |
165 | { |
166 | getBoard(event.getWhere()).setWriter(event.getWho()); |
167 | } |
168 | }; |
169 | eventChannel.registerPushConsumer(priority, filter, consumer); |
170 | } |
171 | |
172 | public Board getBoard(int id) |
173 | { |
174 | return _boards.get(id); |
175 | } |
176 | |
177 | public Board[] getBoards() |
178 | { |
179 | return _boards.values().toArray(new Board[0]); |
180 | } |
181 | |
182 | private final IdentityHolder _identity; |
183 | protected final Map<Integer, Board> _boards = new HashMap<Integer, Board>(); |
184 | } |