Merge lp:~mugle-dev/mugle/dev-api into lp:mugle

Proposed by Scott Ritchie
Status: Merged
Merged at revision: 101
Proposed branch: lp:~mugle-dev/mugle/dev-api
Merge into: lp:mugle
Diff against target: 3635 lines (+2637/-71)
70 files modified
doc/dev/api.rst (+36/-0)
doc/dev/index.rst (+2/-0)
doc/platform/datastore-access.rst (+80/-0)
doc/platform/index.rst (+1/-0)
src/au/edu/unimelb/csse/mugle/client/LoginInfo.java (+9/-0)
src/au/edu/unimelb/csse/mugle/client/api/BadgeService.java (+101/-0)
src/au/edu/unimelb/csse/mugle/client/api/BadgeServiceAsync.java (+102/-0)
src/au/edu/unimelb/csse/mugle/client/api/HighscoreService.java (+46/-0)
src/au/edu/unimelb/csse/mugle/client/api/HighscoreServiceAsync.java (+44/-0)
src/au/edu/unimelb/csse/mugle/client/api/KeyValueService.java (+63/-0)
src/au/edu/unimelb/csse/mugle/client/api/KeyValueServiceAsync.java (+61/-0)
src/au/edu/unimelb/csse/mugle/client/api/Services.java (+50/-0)
src/au/edu/unimelb/csse/mugle/client/api/UserService.java (+41/-0)
src/au/edu/unimelb/csse/mugle/client/api/UserServiceAsync.java (+43/-0)
src/au/edu/unimelb/csse/mugle/client/ui/MugleUiBuilder.java (+144/-0)
src/au/edu/unimelb/csse/mugle/client/ui/PageNav.java (+78/-0)
src/au/edu/unimelb/csse/mugle/server/DataTestServiceImpl.java (+0/-1)
src/au/edu/unimelb/csse/mugle/server/LoginServiceImpl.java (+21/-0)
src/au/edu/unimelb/csse/mugle/server/PMF.java (+1/-1)
src/au/edu/unimelb/csse/mugle/server/api/BadgeServiceImpl.java (+149/-0)
src/au/edu/unimelb/csse/mugle/server/api/HighscoreServiceImpl.java (+65/-0)
src/au/edu/unimelb/csse/mugle/server/api/KeyValueServiceImpl.java (+89/-0)
src/au/edu/unimelb/csse/mugle/server/api/UserServiceImpl.java (+58/-0)
src/au/edu/unimelb/csse/mugle/server/model/AchievementData.java (+20/-6)
src/au/edu/unimelb/csse/mugle/server/model/AchievementGetter.java (+109/-0)
src/au/edu/unimelb/csse/mugle/server/model/DevTeamGetter.java (+78/-0)
src/au/edu/unimelb/csse/mugle/server/model/GameData.java (+12/-1)
src/au/edu/unimelb/csse/mugle/server/model/GameFileData.java (+30/-1)
src/au/edu/unimelb/csse/mugle/server/model/GameGetter.java (+132/-0)
src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairData.java (+6/-0)
src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairGetter.java (+108/-0)
src/au/edu/unimelb/csse/mugle/server/model/ModelDataClass.java (+1/-1)
src/au/edu/unimelb/csse/mugle/server/model/ModelWrapper.java (+1/-1)
src/au/edu/unimelb/csse/mugle/server/model/UserAchievementData.java (+11/-5)
src/au/edu/unimelb/csse/mugle/server/model/UserAchievementGetter.java (+84/-0)
src/au/edu/unimelb/csse/mugle/server/model/UserData.java (+14/-0)
src/au/edu/unimelb/csse/mugle/server/model/UserGameProfileGetter.java (+113/-0)
src/au/edu/unimelb/csse/mugle/server/model/UserGetter.java (+160/-0)
src/au/edu/unimelb/csse/mugle/server/platform/AdminServiceImpl.java (+1/-0)
src/au/edu/unimelb/csse/mugle/server/platform/DeveloperServiceImpl.java (+1/-0)
src/au/edu/unimelb/csse/mugle/server/platform/ServiceHelper.java (+1/-0)
src/au/edu/unimelb/csse/mugle/shared/api/Badge.java (+85/-0)
src/au/edu/unimelb/csse/mugle/shared/api/BadgeError.java (+34/-0)
src/au/edu/unimelb/csse/mugle/shared/api/GameTokenError.java (+34/-0)
src/au/edu/unimelb/csse/mugle/shared/api/KeyError.java (+43/-0)
src/au/edu/unimelb/csse/mugle/shared/model/Achievement.java (+16/-4)
src/au/edu/unimelb/csse/mugle/shared/model/DevTeam.java (+2/-2)
src/au/edu/unimelb/csse/mugle/shared/model/Game.java (+15/-3)
src/au/edu/unimelb/csse/mugle/shared/model/GameFile.java (+26/-4)
src/au/edu/unimelb/csse/mugle/shared/model/GameVersion.java (+2/-1)
src/au/edu/unimelb/csse/mugle/shared/model/InvalidRatingException.java (+4/-1)
src/au/edu/unimelb/csse/mugle/shared/model/KeyValuePair.java (+4/-4)
src/au/edu/unimelb/csse/mugle/shared/model/PromotedGame.java (+2/-2)
src/au/edu/unimelb/csse/mugle/shared/model/User.java (+16/-6)
src/au/edu/unimelb/csse/mugle/shared/model/UserAchievement.java (+2/-8)
src/au/edu/unimelb/csse/mugle/shared/model/UserGameProfile.java (+5/-5)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/AchievementNotExists.java (+40/-0)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamNotExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameNotExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionNotExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameNotExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserExists.java (+5/-1)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserGameProfileNotExists.java (+42/-0)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserNotExists.java (+6/-2)
src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserPrivilegeException.java (+5/-1)
war/WEB-INF/web.xml (+43/-2)
To merge this branch: bzr merge lp:~mugle-dev/mugle/dev-api
Reviewer Review Type Date Requested Status
Matt Giuca Approve
Review via email: mp+57993@code.launchpad.net

Description of the change

Proposing to merge with the trunk since all the service calls are set up. Prageeth and I have decided to make a new branch to work on the UI and platform stuff in regards to the dev-api

To post a comment you must log in.
lp:~mugle-dev/mugle/dev-api updated
142. By Scott Ritchie

Added the mime-type and BlobKey fields to the GameFile so that games
can be stored in the blobstore

143. By Scott Ritchie

Noticed error in the datastore getters in that the queries were still
using the shared.model classes as parameters. This has now been fixed

Revision history for this message
Matt Giuca (mgiuca) wrote :

I'm not sure why this branch adds new UI capabilities. What has that got to do with the developer API?

Anyway, it looks good (from perusing the diff). Were you waiting for me to do a proper review?

Revision history for this message
Matt Giuca (mgiuca) wrote :

OK, looks good to me. Go ahead and merge it.

It seems to do a lot of stuff outside of the dev-api mandate (moving classes around, adding UI capabilities). Try to keep things unrelated to the branch in trunk or a separate branch. But it doesn't matter now (for this branch), since it's done.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'doc/dev/api.rst'
2--- doc/dev/api.rst 1970-01-01 00:00:00 +0000
3+++ doc/dev/api.rst 2011-04-16 12:23:28 +0000
4@@ -0,0 +1,36 @@
5+.. Melbourne University Game-based Learning Environment
6+ Copyright (C) 2011 The University of Melbourne
7+
8+.. This program is free software: you can redistribute it and/or modify
9+ it under the terms of the GNU General Public License as published by
10+ the Free Software Foundation, either version 3 of the License, or
11+ (at your option) any later version.
12+
13+.. This program is distributed in the hope that it will be useful,
14+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+ GNU General Public License for more details.
17+
18+.. You should have received a copy of the GNU General Public License
19+ along with this program. If not, see <http://www.gnu.org/licenses/>.
20+
21+.. _ref-dev-api:
22+
23+Developer API
24+=============
25+
26+MUGLE provides a small, simple API which is available to games for
27+communicating with the server. This allows limited access to the MUGLE
28+database, for both reading and writing information about the current user's
29+profile associated with this game.
30+
31+Each user has a "profile" with each game (the "user-game profile"). This
32+profile associates several pieces of information with the user:
33+
34+* The user's highest score associated with this game.
35+* The badges that the user has unlocked.
36+* An arbitrary key-value mapping (unique to each user), allowing string keys
37+ to be associated with arbitrary object values.
38+
39+All of the APIs available to games developers are available in the package
40+``au.edu.unimelb.csse.mugle.client.api``.
41
42=== modified file 'doc/dev/index.rst'
43--- doc/dev/index.rst 2011-03-11 01:15:21 +0000
44+++ doc/dev/index.rst 2011-04-16 12:23:28 +0000
45@@ -28,3 +28,5 @@
46
47 .. toctree::
48 :maxdepth: 2
49+
50+ api.rst
51
52=== added file 'doc/platform/datastore-access.rst'
53--- doc/platform/datastore-access.rst 1970-01-01 00:00:00 +0000
54+++ doc/platform/datastore-access.rst 2011-04-16 12:23:28 +0000
55@@ -0,0 +1,80 @@
56+.. Melbourne University Game-based Learning Environment
57+ Copyright (C) 2011 The University of Melbourne
58+
59+.. This program is free software: you can redistribute it and/or modify
60+ it under the terms of the GNU General Public License as published by
61+ the Free Software Foundation, either version 3 of the License, or
62+ (at your option) any later version.
63+
64+.. This program is distributed in the hope that it will be useful,
65+ but WITHOUT ANY WARRANTY; without even the implied warranty of
66+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67+ GNU General Public License for more details.
68+
69+.. You should have received a copy of the GNU General Public License
70+ along with this program. If not, see <http://www.gnu.org/licenses/>.
71+
72+Accessing the Datastore
73+=======================
74+
75+To access objects in the datastore, a set of classes called *Getters* have
76+been provided in the package au.edu.unimelb.csse.mugle.server.model, each
77+corresponding to a class in the au.edu.unimelb.csse.mugle.server.model package.
78+This set of classes acts as an interface to the datastore, allowing developers
79+to get Objects from the datastore based on their name, primary key etc.
80+These are then used to pass information over to the client;
81+ - By passing specific information in the class over when called in the
82+ developer API services
83+ - By wrapping the object using the `Datastore wrappers
84+ <data-wrappers.html>`_ before passing them back to the client
85+
86+
87+A variety of methods have been provided for each Getter - allowing you to
88+retrieve an object by its Primary Key, its name, by relations it belongs to
89+(for example the UserGameProfile by the current user and the game they're
90+playing).
91+
92+There are two types of methods in each *Getter*, ones which return the object
93+as read only, and ones which return the object and leave it open for editing.
94+In cases where you want to update the object or call other datastore objects
95+linked to it, you'll need to handle the PersistenceManager yourself; any
96+changes made to an object must be made BEFORE the PersistenceManager is closed
97+for the datastore to be updated with these new changes. Similarly if you need
98+to access an object in the datastore from the object you've currently
99+retrieved, this needs to be done before the PersistenceManager is closed.
100+
101+Example of updating the email of a User
102++++++++++++++++++++++++++++++++++++++++
103+
104+::
105+
106+ public void UpdateEmail(String newEmail) {
107+ UserGetter u = new UserGetter();
108+ UserData user = null;
109+ PersistenceManager pm = PMF.getManager();
110+ try {
111+ user = u.getCurrentUser();
112+ // Any changes must be made before closing the PersistenceManager
113+ user.setEmail(newEmail);
114+ } finally {
115+ pm.close();
116+ }
117+ }
118+
119+Get all the Games a DevTeam has produced
120+++++++++++++++++++++++++++++++++++++++++++++++++
121+
122+::
123+
124+ public Set<GameData> getGame(String devTeamName) {
125+ DevTeamGetter d = new DevTeamGetter();
126+ DevTeamData devTeam = null;
127+ PersistenceManager pm = PMF.getManager();
128+ try {
129+ devTeamData = d.getDevTeam(devTeamName);
130+ return devTeam.getGames();
131+ } finally {
132+ pm.close();
133+ }
134+ }
135+
136
137=== modified file 'doc/platform/index.rst'
138--- doc/platform/index.rst 2011-03-11 01:50:22 +0000
139+++ doc/platform/index.rst 2011-04-16 12:23:28 +0000
140@@ -31,3 +31,4 @@
141 :maxdepth: 2
142
143 data-wrappers.rst
144+ datastore-access.rst
145
146=== modified file 'src/au/edu/unimelb/csse/mugle/client/LoginInfo.java'
147--- src/au/edu/unimelb/csse/mugle/client/LoginInfo.java 2011-03-06 10:21:39 +0000
148+++ src/au/edu/unimelb/csse/mugle/client/LoginInfo.java 2011-04-16 12:23:28 +0000
149@@ -27,6 +27,7 @@
150 private String logoutUrl;
151 private String emailAddress;
152 private String nickname;
153+ private String UserID; //unique ID provided by google
154
155 public boolean isLoggedIn() {
156 return loggedIn;
157@@ -67,4 +68,12 @@
158 public void setNickname(String nickname) {
159 this.nickname = nickname;
160 }
161+
162+public void setUserID(String userID) {
163+ UserID = userID;
164+}
165+
166+public String getUserID() {
167+ return UserID;
168+}
169 }
170
171=== added directory 'src/au/edu/unimelb/csse/mugle/client/api'
172=== added file 'src/au/edu/unimelb/csse/mugle/client/api/BadgeService.java'
173--- src/au/edu/unimelb/csse/mugle/client/api/BadgeService.java 1970-01-01 00:00:00 +0000
174+++ src/au/edu/unimelb/csse/mugle/client/api/BadgeService.java 2011-04-16 12:23:28 +0000
175@@ -0,0 +1,101 @@
176+/* Melbourne University Game-based Learning Environment
177+ * Copyright (C) 2011 The University of Melbourne
178+ *
179+ * This program is free software: you can redistribute it and/or modify
180+ * it under the terms of the GNU Lesser General Public License as published
181+ * by the Free Software Foundation, either version 3 of the License, or
182+ * (at your option) any later version.
183+ *
184+ * This program is distributed in the hope that it will be useful,
185+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
186+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
187+ * GNU Lesser General Public License for more details.
188+ *
189+ * You should have received a copy of the GNU Lesser General Public License
190+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
191+ */
192+
193+package au.edu.unimelb.csse.mugle.client.api;
194+
195+import com.google.gwt.user.client.rpc.RemoteService;
196+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
197+
198+import au.edu.unimelb.csse.mugle.shared.api.Badge;
199+import au.edu.unimelb.csse.mugle.shared.api.BadgeError;
200+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
201+
202+/**
203+ * Developer API for accessing the badges (achievements) system.
204+ * This allows each game to award the user with badges, as well as update the
205+ * progress of badges.
206+ */
207+@RemoteServiceRelativePath("api-badge")
208+public interface BadgeService extends RemoteService
209+{
210+ /** Get a list of badge names for this game.
211+ * @param gameToken The secret token for the current game.
212+ * @return List of strings corresponding to the 'name' field of each
213+ * badge in the current game.
214+ */
215+ public String[] getBadgeNames(String gameToken)
216+ throws GameTokenError;
217+
218+ /** Get the static (user-independent) information about a badge for the
219+ * current game.
220+ * @param gameToken The secret token for the current game.
221+ * @param name The name of the badge.
222+ * @return Information about that badge.
223+ * @throws BadgeError If no badge by that name.
224+ */
225+ public Badge getBadgeInfo(String gameToken, String name)
226+ throws GameTokenError, BadgeError;
227+
228+ /** Sets the Badge to the "achieved" state.
229+ * @param gameToken The secret token for the current game.
230+ * @param name The name of the badge
231+ * @throws BadgeError If no badge by that name.
232+ */
233+ public void setAchieved(String gameToken, String name)
234+ throws GameTokenError, BadgeError;
235+
236+ /** Increments the progress of the badge by the given amount.
237+ * If the progress reaches the maximum for this badge, sets the badge to
238+ * achieved. The progress is capped at the badge maximum.
239+ * @param gameToken The secret token for the current game.
240+ * @param name The name of the badge
241+ * @param amount The amount to increment the badge by. Must not be
242+ * negative.
243+ * @return true if the badge was achieved as a result.
244+ * @throws BadgeError If no badge by that name.
245+ */
246+ public boolean incrementProgress(String gameToken, String name,
247+ int amount) throws GameTokenError, BadgeError;
248+
249+ /** Increments the progress of the badge by 1.
250+ * @param gameToken The secret token for the current game.
251+ * @param name The name of the badge
252+ * @return true if the badge was achieved as a result.
253+ * @throws BadgeError If no badge by that name.
254+ */
255+ public boolean incrementProgress(String gameToken, String name)
256+ throws GameTokenError, BadgeError;
257+
258+ /** Checks whether the badge has been achieved by the player.
259+ * @param gameToken The secret token for the current game.
260+ * @param name The name of the badge
261+ * @return true if achieved, false otherwise
262+ * @throws BadgeError If no badge by that name.
263+ */
264+ public boolean isAchieved(String gameToken, String name)
265+ throws GameTokenError, BadgeError;
266+
267+ /** Returns the progress of the current badge.
268+ * Use getBadgeInfo to retrieve the maximum progress for the badge.
269+ * @param gameToken The secret token for the current game.
270+ * @param name The name of the badge
271+ * @return The progress of the badge
272+ * @throws BadgeError If no badge by that name.
273+ */
274+ public int getProgress(String gameToken, String name)
275+ throws GameTokenError, BadgeError;
276+}
277
278=== added file 'src/au/edu/unimelb/csse/mugle/client/api/BadgeServiceAsync.java'
279--- src/au/edu/unimelb/csse/mugle/client/api/BadgeServiceAsync.java 1970-01-01 00:00:00 +0000
280+++ src/au/edu/unimelb/csse/mugle/client/api/BadgeServiceAsync.java 2011-04-16 12:23:28 +0000
281@@ -0,0 +1,102 @@
282+/* Melbourne University Game-based Learning Environment
283+ * Copyright (C) 2011 The University of Melbourne
284+ *
285+ * This program is free software: you can redistribute it and/or modify
286+ * it under the terms of the GNU Lesser General Public License as published
287+ * by the Free Software Foundation, either version 3 of the License, or
288+ * (at your option) any later version.
289+ *
290+ * This program is distributed in the hope that it will be useful,
291+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
292+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
293+ * GNU Lesser General Public License for more details.
294+ *
295+ * You should have received a copy of the GNU Lesser General Public License
296+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
297+ */
298+
299+package au.edu.unimelb.csse.mugle.client.api;
300+
301+import com.google.gwt.user.client.rpc.AsyncCallback;
302+
303+import au.edu.unimelb.csse.mugle.shared.api.Badge;
304+
305+/**
306+ * Developer async API for accessing the badges (achievements) system.
307+ * This allows each game to award the user with badges, as well as update the
308+ * progress of badges.
309+ */
310+public interface BadgeServiceAsync
311+{
312+ /** Get a list of badge names for this game.
313+ * @param gameToken The secret token for the current game.
314+ * @param callback Called once the operation finishes. On success, passes
315+ * a list of strings corresponding to the 'name' field of each badge in
316+ * the current game.
317+ */
318+ void getBadgeNames(String gameToken, AsyncCallback<String[]> callback);
319+
320+ /** Get the static (user-independent) information about a badge for the
321+ * current game.
322+ * @param gameToken The secret token for the current game.
323+ * @param name The name of the badge.
324+ * @param callback Called once the operation finishes. On success, passes
325+ * information about that badge. Fails (BadgeError) if no badge by that
326+ * name.
327+ */
328+ void getBadgeInfo(String gameToken, String name,
329+ AsyncCallback<Badge> callback);
330+
331+ /** Sets the Badge to the "achieved" state.
332+ * @param gameToken The secret token for the current game.
333+ * @param name The name of the badge
334+ * @param callback Called once the operation finishes. Fails (BadgeError)
335+ * if no badge by that name.
336+ */
337+ void setAchieved(String gameToken, String name,
338+ AsyncCallback<Void> callback);
339+
340+ /** Increments the progress of the badge by the given amount.
341+ * If the progress reaches the maximum for this badge, sets the badge to
342+ * achieved. The progress is capped at the badge maximum.
343+ * @param gameToken The secret token for the current game.
344+ * @param name The name of the badge
345+ * @param amount The amount to increment the badge by. Must not be
346+ * negative.
347+ * @param callback Called once the operation finishes. On success, passes
348+ * true if the badge was achieved as a result. Fails (BadgeError) if no
349+ * badge by that name.
350+ */
351+ void incrementProgress(String gameToken, String name, int amount,
352+ AsyncCallback<Boolean> callback);
353+
354+ /** Increments the progress of the badge by 1.
355+ * @param gameToken The secret token for the current game.
356+ * @param name The name of the badge
357+ * @param callback Called once the operation finishes. On success, passes
358+ * true if the badge was achieved as a result. Fails (BadgeError) if no
359+ * badge by that name.
360+ */
361+ void incrementProgress(String gameToken, String name,
362+ AsyncCallback<Boolean> callback);
363+
364+ /** Checks whether the badge has been achieved by the player.
365+ * @param gameToken The secret token for the current game.
366+ * @param name The name of the badge
367+ * @param callback Called once the operation finishes. On success, passes
368+ * true if the badge is achieved. Fails (BadgeError) if no badge by that
369+ * name.
370+ */
371+ void isAchieved(String gameToken, String name,
372+ AsyncCallback<Boolean> callback);
373+
374+ /** Returns the progress of the current badge.
375+ * Use getBadgeInfo to retrieve the maximum progress for the badge.
376+ * @param gameToken The secret token for the current game.
377+ * @param name The name of the badge
378+ * @param callback Called once the operation finishes. On success, passes
379+ * the progress of the badge. Fails (BadgeError) if no badge by that name.
380+ */
381+ void getProgress(String gameToken, String name,
382+ AsyncCallback<Integer> callback);
383+}
384
385=== added file 'src/au/edu/unimelb/csse/mugle/client/api/HighscoreService.java'
386--- src/au/edu/unimelb/csse/mugle/client/api/HighscoreService.java 1970-01-01 00:00:00 +0000
387+++ src/au/edu/unimelb/csse/mugle/client/api/HighscoreService.java 2011-04-16 12:23:28 +0000
388@@ -0,0 +1,46 @@
389+/* Melbourne University Game-based Learning Environment
390+ * Copyright (C) 2011 The University of Melbourne
391+ *
392+ * This program is free software: you can redistribute it and/or modify
393+ * it under the terms of the GNU Lesser General Public License as published
394+ * by the Free Software Foundation, either version 3 of the License, or
395+ * (at your option) any later version.
396+ *
397+ * This program is distributed in the hope that it will be useful,
398+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
399+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
400+ * GNU Lesser General Public License for more details.
401+ *
402+ * You should have received a copy of the GNU Lesser General Public License
403+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
404+ */
405+
406+package au.edu.unimelb.csse.mugle.client.api;
407+
408+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
409+
410+import com.google.gwt.user.client.rpc.RemoteService;
411+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
412+
413+/**
414+ * Developer API for accessing the current user's high-score.
415+ * This allows the game to save the user's highest score.
416+ */
417+@RemoteServiceRelativePath("api-highscore")
418+public interface HighscoreService extends RemoteService
419+{
420+ /** Saves the score for the current player. If this is better than the
421+ * player's current high score, sets the new high score. Otherwise, does
422+ * nothing.
423+ * @param gameToken The secret token for the current game.
424+ * @param score The player's score.
425+ */
426+ public void saveScore(String gameToken, int score)
427+ throws GameTokenError;
428+
429+ /** Gets the highest score of the current player.
430+ * @param gameToken The secret token for the current game.
431+ * @return The player's highest score.
432+ */
433+ public int getHighScore(String gameToken) throws GameTokenError;
434+}
435
436=== added file 'src/au/edu/unimelb/csse/mugle/client/api/HighscoreServiceAsync.java'
437--- src/au/edu/unimelb/csse/mugle/client/api/HighscoreServiceAsync.java 1970-01-01 00:00:00 +0000
438+++ src/au/edu/unimelb/csse/mugle/client/api/HighscoreServiceAsync.java 2011-04-16 12:23:28 +0000
439@@ -0,0 +1,44 @@
440+/* Melbourne University Game-based Learning Environment
441+ * Copyright (C) 2011 The University of Melbourne
442+ *
443+ * This program is free software: you can redistribute it and/or modify
444+ * it under the terms of the GNU Lesser General Public License as published
445+ * by the Free Software Foundation, either version 3 of the License, or
446+ * (at your option) any later version.
447+ *
448+ * This program is distributed in the hope that it will be useful,
449+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
450+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
451+ * GNU Lesser General Public License for more details.
452+ *
453+ * You should have received a copy of the GNU Lesser General Public License
454+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
455+ */
456+
457+package au.edu.unimelb.csse.mugle.client.api;
458+
459+import com.google.gwt.user.client.rpc.AsyncCallback;
460+
461+/**
462+ * Developer async API for accessing the current user's high-score.
463+ * This allows the game to save the user's highest score.
464+ */
465+public interface HighscoreServiceAsync
466+{
467+ /** Saves the score for the current player. If this is better than the
468+ * player's current high score, sets the new high score. Otherwise, does
469+ * nothing.
470+ * @param gameToken The secret token for the current game.
471+ * @param score The player's score.
472+ * @param callback Called once the operation finishes.
473+ */
474+ void saveScore(String gameToken, int score,
475+ AsyncCallback<Void> callback);
476+
477+ /** Gets the highest score of the current player.
478+ * @param gameToken The secret token for the current game.
479+ * @param callback Called once the operation finishes. On success, passes
480+ * the player's highest score.
481+ */
482+ void getHighScore(String gameToken, AsyncCallback<Integer> callback);
483+}
484
485=== added file 'src/au/edu/unimelb/csse/mugle/client/api/KeyValueService.java'
486--- src/au/edu/unimelb/csse/mugle/client/api/KeyValueService.java 1970-01-01 00:00:00 +0000
487+++ src/au/edu/unimelb/csse/mugle/client/api/KeyValueService.java 2011-04-16 12:23:28 +0000
488@@ -0,0 +1,63 @@
489+/* Melbourne University Game-based Learning Environment
490+ * Copyright (C) 2011 The University of Melbourne
491+ *
492+ * This program is free software: you can redistribute it and/or modify
493+ * it under the terms of the GNU Lesser General Public License as published
494+ * by the Free Software Foundation, either version 3 of the License, or
495+ * (at your option) any later version.
496+ *
497+ * This program is distributed in the hope that it will be useful,
498+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
499+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
500+ * GNU Lesser General Public License for more details.
501+ *
502+ * You should have received a copy of the GNU Lesser General Public License
503+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
504+ */
505+
506+package au.edu.unimelb.csse.mugle.client.api;
507+
508+import java.io.Serializable;
509+
510+import com.google.gwt.user.client.rpc.RemoteService;
511+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
512+
513+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
514+import au.edu.unimelb.csse.mugle.shared.api.KeyError;
515+
516+/**
517+ * Developer API for accessing the key/value store.
518+ * This allows each game to associate arbitrary data with string keys,
519+ * independently for each user.
520+ */
521+@RemoteServiceRelativePath("api-keyvalue")
522+public interface KeyValueService extends RemoteService
523+{
524+ /** Store an object in the key-value store.
525+ * The value will be specific to the current user, and will only be able
526+ * to be retrieved by the same user.
527+ * @param gameToken The secret token for the current game.
528+ * @param key The key to associate the object with.
529+ * @param value The object to store.
530+ */
531+ public void put(String gameToken, String key, Serializable value)
532+ throws GameTokenError;
533+
534+ /** Retrieve an object from the key-value store.
535+ * The value will be the one stored by the current user.
536+ * @param gameToken The secret token for the current game.
537+ * @param key The key the object is associated with.
538+ * @return The object associated with the key.
539+ * @throws KeyError If no object is associated with that key.
540+ */
541+ public Serializable get(String gameToken, String key)
542+ throws GameTokenError, KeyError;
543+
544+ /** Test whether a key has an associated object for the current user.
545+ * @param gameToken The secret token for the current game.
546+ * @param key The key the object is associated with.
547+ * @return True if a value is associated with the key.
548+ */
549+ public boolean containsKey(String gameToken, String key)
550+ throws GameTokenError;
551+}
552
553=== added file 'src/au/edu/unimelb/csse/mugle/client/api/KeyValueServiceAsync.java'
554--- src/au/edu/unimelb/csse/mugle/client/api/KeyValueServiceAsync.java 1970-01-01 00:00:00 +0000
555+++ src/au/edu/unimelb/csse/mugle/client/api/KeyValueServiceAsync.java 2011-04-16 12:23:28 +0000
556@@ -0,0 +1,61 @@
557+/* Melbourne University Game-based Learning Environment
558+ * Copyright (C) 2011 The University of Melbourne
559+ *
560+ * This program is free software: you can redistribute it and/or modify
561+ * it under the terms of the GNU Lesser General Public License as published
562+ * by the Free Software Foundation, either version 3 of the License, or
563+ * (at your option) any later version.
564+ *
565+ * This program is distributed in the hope that it will be useful,
566+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
567+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
568+ * GNU Lesser General Public License for more details.
569+ *
570+ * You should have received a copy of the GNU Lesser General Public License
571+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
572+ */
573+
574+package au.edu.unimelb.csse.mugle.client.api;
575+
576+import java.io.Serializable;
577+
578+import com.google.gwt.user.client.rpc.AsyncCallback;
579+
580+/**
581+ * Developer async API for accessing the key/value store.
582+ * This allows each game to associate arbitrary data with string keys,
583+ * independently for each user.
584+ */
585+public interface KeyValueServiceAsync
586+{
587+ /** Store an object in the key-value store.
588+ * The value will be specific to the current user, and will only be able
589+ * to be retrieved by the same user.
590+ * @param gameToken The secret token for the current game.
591+ * @param key The key to associate the object with.
592+ * @param value The object to store.
593+ * @param callback Called once the operation finishes.
594+ */
595+ public void put(String gameToken, String key, Serializable value,
596+ AsyncCallback<Void> callback);
597+
598+ /** Retrieve an object from the key-value store.
599+ * The value will be the one stored by the current user.
600+ * @param gameToken The secret token for the current game.
601+ * @param key The key the object is associated with.
602+ * @param callback Called once the operation finishes. On success, passes
603+ * the object associated with the key. Fails (KeyError) if no object is
604+ * associated with that key.
605+ */
606+ public void get(String gameToken, String key,
607+ AsyncCallback<Serializable> callback);
608+
609+ /** Test whether a key has an associated object for the current user.
610+ * @param gameToken The secret token for the current game.
611+ * @param key The key the object is associated with.
612+ * @param callback Called once the operation finishes. On success, passes
613+ * true if a value is associated with the key.
614+ */
615+ public void containsKey(String gameToken, String key,
616+ AsyncCallback<Boolean> callback);
617+}
618
619=== added file 'src/au/edu/unimelb/csse/mugle/client/api/Services.java'
620--- src/au/edu/unimelb/csse/mugle/client/api/Services.java 1970-01-01 00:00:00 +0000
621+++ src/au/edu/unimelb/csse/mugle/client/api/Services.java 2011-04-16 12:23:28 +0000
622@@ -0,0 +1,50 @@
623+/* Melbourne University Game-based Learning Environment
624+ * Copyright (C) 2011 The University of Melbourne
625+ *
626+ * This program is free software: you can redistribute it and/or modify
627+ * it under the terms of the GNU Lesser General Public License as published
628+ * by the Free Software Foundation, either version 3 of the License, or
629+ * (at your option) any later version.
630+ *
631+ * This program is distributed in the hope that it will be useful,
632+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
633+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
634+ * GNU Lesser General Public License for more details.
635+ *
636+ * You should have received a copy of the GNU Lesser General Public License
637+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
638+ */
639+
640+package au.edu.unimelb.csse.mugle.client.api;
641+
642+import com.google.gwt.core.client.GWT;
643+import com.google.gwt.user.client.rpc.ServiceDefTarget;
644+
645+/** Provides access to pre-initialised instances of all the asynchronous
646+ * services offered by MUGLE.
647+ */
648+public class Services
649+{
650+ /** An instance of the asynchronous user service. */
651+ public static final UserServiceAsync user =
652+ GWT.create(UserService.class);
653+ /** An instance of the asynchronous key-value service. */
654+ public static final KeyValueServiceAsync keyvalue =
655+ GWT.create(KeyValueService.class);
656+ /** An instance of the asynchronous badge service. */
657+ public static final BadgeServiceAsync badges =
658+ GWT.create(BadgeService.class);
659+ /** An instance of the asynchronous high score service. */
660+ public static final HighscoreServiceAsync highscore =
661+ GWT.create(HighscoreService.class);
662+
663+ static
664+ {
665+ ((ServiceDefTarget) badges).setServiceEntryPoint("/mugle/api-badge");
666+ ((ServiceDefTarget) highscore).setServiceEntryPoint(
667+ "/mugle/api-highscore");
668+ ((ServiceDefTarget) keyvalue).setServiceEntryPoint(
669+ "/mugle/api-keyvalue");
670+ ((ServiceDefTarget) user).setServiceEntryPoint("/mugle/api-user");
671+ }
672+}
673
674=== added file 'src/au/edu/unimelb/csse/mugle/client/api/UserService.java'
675--- src/au/edu/unimelb/csse/mugle/client/api/UserService.java 1970-01-01 00:00:00 +0000
676+++ src/au/edu/unimelb/csse/mugle/client/api/UserService.java 2011-04-16 12:23:28 +0000
677@@ -0,0 +1,41 @@
678+/* Melbourne University Game-based Learning Environment
679+ * Copyright (C) 2011 The University of Melbourne
680+ *
681+ * This program is free software: you can redistribute it and/or modify
682+ * it under the terms of the GNU Lesser General Public License as published
683+ * by the Free Software Foundation, either version 3 of the License, or
684+ * (at your option) any later version.
685+ *
686+ * This program is distributed in the hope that it will be useful,
687+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
688+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
689+ * GNU Lesser General Public License for more details.
690+ *
691+ * You should have received a copy of the GNU Lesser General Public License
692+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
693+ */
694+
695+package au.edu.unimelb.csse.mugle.client.api;
696+
697+import com.google.gwt.user.client.rpc.RemoteService;
698+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
699+
700+/**
701+ * Developer API for accessing information about the current user.
702+ */
703+@RemoteServiceRelativePath("api-user")
704+public interface UserService extends RemoteService
705+{
706+ /** Gets the the nickname of the user playing the game.
707+ * This should be used whenever the user's name needs to be displayed.
708+ * Note that this nickname may change, so it should not be used to
709+ * permanently associate information with the user (see getUserID).
710+ */
711+ public String getUserNickName();
712+
713+ /** Gets the user ID of the user playing the game.
714+ * This is guaranteed never to change for this user, so it should be used
715+ * any time some permanent information needs to be associated with a user.
716+ */
717+ public String getUserID();
718+}
719
720=== added file 'src/au/edu/unimelb/csse/mugle/client/api/UserServiceAsync.java'
721--- src/au/edu/unimelb/csse/mugle/client/api/UserServiceAsync.java 1970-01-01 00:00:00 +0000
722+++ src/au/edu/unimelb/csse/mugle/client/api/UserServiceAsync.java 2011-04-16 12:23:28 +0000
723@@ -0,0 +1,43 @@
724+/* Melbourne University Game-based Learning Environment
725+ * Copyright (C) 2011 The University of Melbourne
726+ *
727+ * This program is free software: you can redistribute it and/or modify
728+ * it under the terms of the GNU Lesser General Public License as published
729+ * by the Free Software Foundation, either version 3 of the License, or
730+ * (at your option) any later version.
731+ *
732+ * This program is distributed in the hope that it will be useful,
733+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
734+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
735+ * GNU Lesser General Public License for more details.
736+ *
737+ * You should have received a copy of the GNU Lesser General Public License
738+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
739+ */
740+
741+package au.edu.unimelb.csse.mugle.client.api;
742+
743+import com.google.gwt.user.client.rpc.AsyncCallback;
744+
745+/**
746+ * Developer async API for accessing information about the current user.
747+ */
748+public interface UserServiceAsync
749+{
750+ /** Gets the the nickname of the user playing the game.
751+ * This should be used whenever the user's name needs to be displayed.
752+ * Note that this nickname may change, so it should not be used to
753+ * permanently associate information with the user (see getUserID).
754+ * @param callback Called once the operation finishes. On success, passes
755+ * the nickname.
756+ */
757+ void getUserNickName(AsyncCallback<String> callback);
758+
759+ /** Gets the user ID of the user playing the game.
760+ * This is guaranteed never to change for this user, so it should be used
761+ * any time some permanent information needs to be associated with a user.
762+ * @param callback Called once the operation finishes. On success, passes
763+ * the user ID.
764+ */
765+ void getUserID(AsyncCallback<String> callback);
766+}
767
768=== added directory 'src/au/edu/unimelb/csse/mugle/client/ui'
769=== added file 'src/au/edu/unimelb/csse/mugle/client/ui/MugleUiBuilder.java'
770--- src/au/edu/unimelb/csse/mugle/client/ui/MugleUiBuilder.java 1970-01-01 00:00:00 +0000
771+++ src/au/edu/unimelb/csse/mugle/client/ui/MugleUiBuilder.java 2011-04-16 12:23:28 +0000
772@@ -0,0 +1,144 @@
773+package au.edu.unimelb.csse.mugle.client.ui;
774+
775+import java.util.Collection;
776+import java.util.Iterator;
777+
778+import com.google.gwt.event.dom.client.ClickHandler;
779+import com.google.gwt.user.client.ui.Button;
780+import com.google.gwt.user.client.ui.CellPanel;
781+import com.google.gwt.user.client.ui.FlexTable;
782+import com.google.gwt.user.client.ui.HorizontalPanel;
783+import com.google.gwt.user.client.ui.Label;
784+import com.google.gwt.user.client.ui.VerticalPanel;
785+import com.google.gwt.user.client.ui.Widget;
786+
787+public class MugleUiBuilder {
788+
789+ private MugleUiBuilder() { }
790+
791+ public static CellPanel buildStringTable(Collection<Collection<String>> list, Collection<String> headers) {
792+ return buildStringTable(list, null);
793+ }
794+
795+ public static CellPanel buildStringTable(Collection<Collection<String>> list, Collection<String> headers, PageNav pageNav) {
796+
797+ // build panel
798+ VerticalPanel panel = new VerticalPanel();
799+
800+ // build table
801+
802+ FlexTable table = new FlexTable();
803+
804+ int row = 0;
805+ int col = 0;
806+
807+ Iterator<String> it = headers.iterator();
808+ while (it.hasNext()) {
809+ table.setText(row, col, it.next());
810+ col++;
811+ }
812+ row++;
813+
814+ Iterator<Collection<String>> iter = list.iterator();
815+ while (iter.hasNext()) {
816+ Iterator<String> sit = iter.next().iterator();
817+ while (sit.hasNext()) {
818+ table.setText(row, col, sit.next());
819+ col++;
820+ }
821+ // check the items per page restriction
822+ if (pageNav != null && pageNav.getItemsPerPage() >= row) { break; }
823+ row++;
824+
825+ }
826+
827+ // add table to panel
828+ panel.add(table);
829+
830+ // add navigation details
831+ if (pageNav != null) {
832+ panel.add(getNagivationDetails(pageNav));
833+ }
834+
835+ return panel;
836+
837+ }
838+
839+ public static CellPanel buildWidgetTable(Collection<Collection<Widget>> list, Collection<String> headers) {
840+ return buildWidgetTable(list, headers, null);
841+ }
842+
843+ public static CellPanel buildWidgetTable(Collection<Collection<Widget>> list, Collection<String> headers, PageNav pageNav) {
844+
845+ // build panel
846+ VerticalPanel panel = new VerticalPanel();
847+
848+ // build table
849+
850+ FlexTable table = new FlexTable();
851+
852+ int row = 0;
853+ int col = 0;
854+
855+ Iterator<String> it = headers.iterator();
856+ while (it.hasNext()) {
857+ table.setText(row, col, it.next());
858+ col++;
859+ }
860+ row++;
861+
862+ Iterator<Collection<Widget>> iter = list.iterator();
863+ while (iter.hasNext()) {
864+ Iterator<Widget> wit = iter.next().iterator();
865+ while (wit.hasNext()) {
866+ table.setWidget(row, col, wit.next());
867+ col++;
868+ }
869+ // check the items per page restriction
870+ if (pageNav != null && pageNav.getItemsPerPage() >= row) { break; }
871+ row++;
872+ }
873+
874+ // add table to panel
875+ panel.add(table);
876+
877+ // add navigation details
878+ if (pageNav != null) {
879+ panel.add(getNagivationDetails(pageNav));
880+ }
881+
882+ return panel;
883+
884+ }
885+
886+ private static Widget getNagivationDetails(PageNav pageNav) {
887+
888+ if (pageNav == null) {
889+ // TODO throw Exception or handle error
890+ }
891+
892+ HorizontalPanel hp = new HorizontalPanel();
893+ hp.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
894+
895+ addNewButtonToPanel(hp, "<<", pageNav.getFirstClicked());
896+ addNewButtonToPanel(hp, "<", pageNav.getPrevClicked());
897+
898+ // TODO add links to pages around
899+ //hp.add(new Label( String.format("%d of %d", pageNav.getCurrPage(), pageNav.getMaxPages()) ));
900+ hp.add(new Label( String.valueOf(pageNav.getCurrPage()) ));
901+
902+ addNewButtonToPanel(hp, ">", pageNav.getNextClicked());
903+ addNewButtonToPanel(hp, ">>", pageNav.getLastClicked());
904+
905+ return hp;
906+
907+ }
908+
909+ private static void addNewButtonToPanel(CellPanel panel, String text, ClickHandler handler) {
910+ Button b = new Button();
911+ b.setText(text);
912+ if (handler != null) { b.addClickHandler(handler); }
913+ panel.add(b);
914+ }
915+
916+}
917
918=== added file 'src/au/edu/unimelb/csse/mugle/client/ui/PageNav.java'
919--- src/au/edu/unimelb/csse/mugle/client/ui/PageNav.java 1970-01-01 00:00:00 +0000
920+++ src/au/edu/unimelb/csse/mugle/client/ui/PageNav.java 2011-04-16 12:23:28 +0000
921@@ -0,0 +1,78 @@
922+package au.edu.unimelb.csse.mugle.client.ui;
923+
924+import com.google.gwt.event.dom.client.ClickHandler;
925+
926+public class PageNav {
927+
928+ private int currPage = 0;
929+ private int maxPages = 0;
930+ private int itemsPerPage = 0;
931+
932+ private ClickHandler firstClicked = null;
933+ private ClickHandler prevClicked = null;
934+ private ClickHandler nextClicked = null;
935+ private ClickHandler lastClicked = null;
936+
937+ public PageNav(int currPage, int maxPages, int itemsPerPage) {
938+ this.currPage = currPage;
939+ this.maxPages = maxPages;
940+ this.itemsPerPage = itemsPerPage;
941+ }
942+
943+ public int getCurrPage() {
944+ return this.currPage;
945+ }
946+
947+ public void setCurrPage(int currPage) {
948+ this.currPage = currPage;
949+ }
950+
951+ public int getMaxPages() {
952+ return this.maxPages;
953+ }
954+
955+ public void setMaxPages(int maxPages) {
956+ this.maxPages = maxPages;
957+ }
958+
959+ public int getItemsPerPage() {
960+ return this.itemsPerPage;
961+ }
962+
963+ public void setItemsPerPage(int itemsPerPage) {
964+ this.itemsPerPage = itemsPerPage;
965+ }
966+
967+ public ClickHandler getFirstClicked() {
968+ return this.firstClicked;
969+ }
970+
971+ public void setFirstClicked(ClickHandler firstClicked) {
972+ this.firstClicked = firstClicked;
973+ }
974+
975+ public ClickHandler getPrevClicked() {
976+ return this.prevClicked;
977+ }
978+
979+ public void setPrevClicked(ClickHandler prevClicked) {
980+ this.prevClicked = prevClicked;
981+ }
982+
983+ public ClickHandler getNextClicked() {
984+ return this.nextClicked;
985+ }
986+
987+ public void setNextClicked(ClickHandler nextClicked) {
988+ this.nextClicked = nextClicked;
989+ }
990+
991+ public ClickHandler getLastClicked() {
992+ return this.lastClicked;
993+ }
994+
995+ public void setLastClicked(ClickHandler lastClicked) {
996+ this.lastClicked = lastClicked;
997+ }
998+
999+}
1000
1001=== modified file 'src/au/edu/unimelb/csse/mugle/server/DataTestServiceImpl.java'
1002--- src/au/edu/unimelb/csse/mugle/server/DataTestServiceImpl.java 2011-03-30 15:46:59 +0000
1003+++ src/au/edu/unimelb/csse/mugle/server/DataTestServiceImpl.java 2011-04-16 12:23:28 +0000
1004@@ -22,7 +22,6 @@
1005
1006 import au.edu.unimelb.csse.mugle.client.*;
1007 import au.edu.unimelb.csse.mugle.server.model.*;
1008-import au.edu.unimelb.csse.mugle.server.platform.*;
1009 import au.edu.unimelb.csse.mugle.shared.model.*;
1010
1011 @SuppressWarnings("serial")
1012
1013=== modified file 'src/au/edu/unimelb/csse/mugle/server/LoginServiceImpl.java'
1014--- src/au/edu/unimelb/csse/mugle/server/LoginServiceImpl.java 2011-03-06 10:23:58 +0000
1015+++ src/au/edu/unimelb/csse/mugle/server/LoginServiceImpl.java 2011-04-16 12:23:28 +0000
1016@@ -36,6 +36,7 @@
1017 loginInfo.setLoggedIn(true);
1018 loginInfo.setEmailAddress(user.getEmail());
1019 loginInfo.setNickname(user.getNickname());
1020+ loginInfo.setUserID(user.getUserId());
1021 loginInfo.setLogoutUrl(userService.createLogoutURL(requestUri));
1022 } else {
1023 loginInfo.setLoggedIn(false);
1024@@ -43,5 +44,25 @@
1025 }
1026 return loginInfo;
1027 }
1028+
1029+ /* For server side purposes only,
1030+ * Gets the currently logged in user as above, but without the
1031+ * Host's url. Used in most server side service implementations
1032+ */
1033+ public LoginInfo getCurrentUser() {
1034+ UserService userService = UserServiceFactory.getUserService();
1035+ User user = userService.getCurrentUser();
1036+ LoginInfo loginInfo = new LoginInfo();
1037+
1038+ if (user != null) {
1039+ loginInfo.setLoggedIn(true);
1040+ loginInfo.setEmailAddress(user.getEmail());
1041+ loginInfo.setNickname(user.getNickname());
1042+ loginInfo.setUserID(user.getUserId());
1043+ } else {
1044+ loginInfo.setLoggedIn(false);
1045+ }
1046+ return loginInfo;
1047+ }
1048
1049 }
1050
1051=== renamed file 'src/au/edu/unimelb/csse/mugle/server/platform/PMF.java' => 'src/au/edu/unimelb/csse/mugle/server/PMF.java'
1052--- src/au/edu/unimelb/csse/mugle/server/platform/PMF.java 2011-03-06 10:18:13 +0000
1053+++ src/au/edu/unimelb/csse/mugle/server/PMF.java 2011-04-16 12:23:28 +0000
1054@@ -15,7 +15,7 @@
1055 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1056 */
1057
1058-package au.edu.unimelb.csse.mugle.server.platform;
1059+package au.edu.unimelb.csse.mugle.server;
1060
1061 import javax.jdo.JDOHelper;
1062 import javax.jdo.PersistenceManager;
1063
1064=== added directory 'src/au/edu/unimelb/csse/mugle/server/api'
1065=== added file 'src/au/edu/unimelb/csse/mugle/server/api/BadgeServiceImpl.java'
1066--- src/au/edu/unimelb/csse/mugle/server/api/BadgeServiceImpl.java 1970-01-01 00:00:00 +0000
1067+++ src/au/edu/unimelb/csse/mugle/server/api/BadgeServiceImpl.java 2011-04-16 12:23:28 +0000
1068@@ -0,0 +1,149 @@
1069+/* Melbourne University Game-based Learning Environment
1070+ * Copyright (C) 2011 The University of Melbourne
1071+ *
1072+ * This program is free software: you can redistribute it and/or modify
1073+ * it under the terms of the GNU General Public License as published by
1074+ * the Free Software Foundation, either version 3 of the License, or
1075+ * (at your option) any later version.
1076+ *
1077+ * This program is distributed in the hope that it will be useful,
1078+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1079+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1080+ * GNU General Public License for more details.
1081+ *
1082+ * You should have received a copy of the GNU General Public License
1083+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1084+ */
1085+
1086+package au.edu.unimelb.csse.mugle.server.api;
1087+
1088+import java.util.ArrayList;
1089+
1090+import au.edu.unimelb.csse.mugle.client.api.BadgeService;
1091+import au.edu.unimelb.csse.mugle.server.PMF;
1092+import au.edu.unimelb.csse.mugle.server.model.AchievementData;
1093+import au.edu.unimelb.csse.mugle.server.model.AchievementGetter;
1094+import au.edu.unimelb.csse.mugle.server.model.GameData;
1095+import au.edu.unimelb.csse.mugle.server.model.GameGetter;
1096+import au.edu.unimelb.csse.mugle.server.model.UserAchievementData;
1097+import au.edu.unimelb.csse.mugle.server.model.UserAchievementGetter;
1098+import au.edu.unimelb.csse.mugle.shared.api.Badge;
1099+import au.edu.unimelb.csse.mugle.shared.api.BadgeError;
1100+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
1101+
1102+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.*;
1103+
1104+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
1105+
1106+import javax.jdo.PersistenceManager;
1107+
1108+
1109+/**
1110+ * The server side implementation of KeyValueService.
1111+ */
1112+@SuppressWarnings("serial")
1113+public class BadgeServiceImpl extends RemoteServiceServlet
1114+ implements BadgeService
1115+{
1116+ private UserAchievementData getUserAchievement(String gameToken, String name) throws GameTokenError, BadgeError {
1117+ PersistenceManager pm = PMF.getManager();
1118+ try {
1119+ return this.getUserAchievement(pm, gameToken, name);
1120+ } finally {
1121+ pm.close();
1122+ }
1123+ }
1124+
1125+ private UserAchievementData getUserAchievement(PersistenceManager pm, String gameToken, String name) throws GameTokenError, BadgeError {
1126+ UserAchievementGetter u = new UserAchievementGetter();
1127+ try {
1128+ return u.getUserAchievement(pm, name, gameToken);
1129+ } catch (UserNotExists e) {
1130+ throw new Error(e);
1131+ } catch (AchievementNotExists e) {
1132+ throw new BadgeError(e.getMessage());
1133+ }
1134+ }
1135+
1136+ @Override
1137+ public String[] getBadgeNames(String gameToken) throws GameTokenError {
1138+ ArrayList<String> toReturn = new ArrayList<String>();
1139+ GameGetter g = new GameGetter();
1140+ GameData curGame = null;
1141+
1142+ curGame = g.getCurrentGame(gameToken);
1143+
1144+ for (AchievementData a: curGame.getAchievements()) {
1145+ toReturn.add(a.getName());
1146+ }
1147+ return (String[]) toReturn.toArray();
1148+ }
1149+
1150+ @Override
1151+ public Badge getBadgeInfo(String gameToken, String name)
1152+ throws GameTokenError, BadgeError {
1153+ PersistenceManager pm = PMF.getManager();
1154+ AchievementData a;
1155+ try {
1156+ AchievementGetter ag = new AchievementGetter();
1157+ a = ag.getAchievement(pm, name, gameToken);;
1158+ } catch (AchievementNotExists e) {
1159+ throw new BadgeError(e.getMessage());
1160+ } finally {
1161+ pm.close();
1162+ }
1163+ // XXX The badge API requires both a short name and a display name
1164+ // Currently use the same name for both; requires changes to
1165+ // Achievement class.
1166+ return new Badge(a.getName(), a.getName(), a.getDescription(),
1167+ a.getMaxProgress());
1168+ }
1169+
1170+ @Override
1171+ public boolean isAchieved(String gameToken, String name) throws GameTokenError, BadgeError {
1172+ return this.getUserAchievement(gameToken, name).getAchieved();
1173+ }
1174+
1175+ @Override
1176+ public int getProgress(String gameToken, String name) throws GameTokenError, BadgeError {
1177+ return this.getUserAchievement(gameToken, name).getProgress();
1178+ }
1179+
1180+ @Override
1181+ public boolean incrementProgress(String gameToken, String name, int amount) throws GameTokenError, BadgeError {
1182+ PersistenceManager pm = PMF.getManager();
1183+
1184+ if (amount < 0)
1185+ throw new BadgeError("incrementProgress called with negative amount");
1186+
1187+ try {
1188+ UserAchievementData ua = this.getUserAchievement(pm, gameToken, name);
1189+ if (ua.getAchievement().getMaxProgress() == 0) {
1190+ throw new BadgeError("incrementProgress called on non-progress badge " + name);
1191+ }
1192+ return ua.addProgress(amount);
1193+ } finally {
1194+ pm.close();
1195+ }
1196+ }
1197+
1198+ @Override
1199+ public boolean incrementProgress(String gameToken, String name) throws GameTokenError, BadgeError{
1200+ return incrementProgress(gameToken, name, 1);
1201+ }
1202+
1203+ @Override
1204+ public void setAchieved(String gameToken, String name) throws GameTokenError, BadgeError {
1205+ PersistenceManager pm = PMF.getManager();
1206+
1207+ try {
1208+ UserAchievementData ua = this.getUserAchievement(pm, gameToken, name);
1209+ ua.setAchieved(true);
1210+ // also need to set the progress
1211+ ua.setProgress(ua.getAchievement().getMaxProgress());
1212+ } finally {
1213+ pm.close();
1214+ }
1215+ }
1216+
1217+}
1218
1219=== added file 'src/au/edu/unimelb/csse/mugle/server/api/HighscoreServiceImpl.java'
1220--- src/au/edu/unimelb/csse/mugle/server/api/HighscoreServiceImpl.java 1970-01-01 00:00:00 +0000
1221+++ src/au/edu/unimelb/csse/mugle/server/api/HighscoreServiceImpl.java 2011-04-16 12:23:28 +0000
1222@@ -0,0 +1,65 @@
1223+/* Melbourne University Game-based Learning Environment
1224+ * Copyright (C) 2011 The University of Melbourne
1225+ *
1226+ * This program is free software: you can redistribute it and/or modify
1227+ * it under the terms of the GNU General Public License as published by
1228+ * the Free Software Foundation, either version 3 of the License, or
1229+ * (at your option) any later version.
1230+ *
1231+ * This program is distributed in the hope that it will be useful,
1232+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1233+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1234+ * GNU General Public License for more details.
1235+ *
1236+ * You should have received a copy of the GNU General Public License
1237+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1238+ */
1239+
1240+package au.edu.unimelb.csse.mugle.server.api;
1241+
1242+import au.edu.unimelb.csse.mugle.client.api.HighscoreService;
1243+import au.edu.unimelb.csse.mugle.server.PMF;
1244+import au.edu.unimelb.csse.mugle.server.model.UserGameProfileGetter;
1245+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
1246+import au.edu.unimelb.csse.mugle.server.model.UserGameProfileData;
1247+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserNotExists;
1248+
1249+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
1250+
1251+import javax.jdo.PersistenceManager;
1252+
1253+
1254+/**
1255+ * The server side implementation of KeyValueService.
1256+ */
1257+@SuppressWarnings("serial")
1258+public class HighscoreServiceImpl extends RemoteServiceServlet
1259+ implements HighscoreService
1260+{
1261+
1262+ public int getHighScore(String gameToken) throws GameTokenError {
1263+ UserGameProfileGetter u = new UserGameProfileGetter();
1264+ UserGameProfileData ugp;
1265+ try {
1266+ ugp = u.getCurrentUserGameProfile(gameToken);
1267+ } catch (UserNotExists e) {
1268+ throw new Error(e);
1269+ }
1270+ return ugp.getHighscore();
1271+ }
1272+
1273+ public void saveScore(String gameToken, int score) throws GameTokenError {
1274+ PersistenceManager pm = PMF.getManager();
1275+ UserGameProfileGetter u = new UserGameProfileGetter();
1276+ UserGameProfileData ugp = null;
1277+ try {
1278+ ugp = u.getCurrentUserGameProfile(pm, gameToken);
1279+ if (score > ugp.getHighscore())
1280+ ugp.setHighscore(score);
1281+ } catch (UserNotExists e) {
1282+ throw new Error(e);
1283+ } finally {
1284+ pm.close();
1285+ }
1286+ }
1287+}
1288
1289=== added file 'src/au/edu/unimelb/csse/mugle/server/api/KeyValueServiceImpl.java'
1290--- src/au/edu/unimelb/csse/mugle/server/api/KeyValueServiceImpl.java 1970-01-01 00:00:00 +0000
1291+++ src/au/edu/unimelb/csse/mugle/server/api/KeyValueServiceImpl.java 2011-04-16 12:23:28 +0000
1292@@ -0,0 +1,89 @@
1293+/* Melbourne University Game-based Learning Environment
1294+ * Copyright (C) 2011 The University of Melbourne
1295+ *
1296+ * This program is free software: you can redistribute it and/or modify
1297+ * it under the terms of the GNU General Public License as published by
1298+ * the Free Software Foundation, either version 3 of the License, or
1299+ * (at your option) any later version.
1300+ *
1301+ * This program is distributed in the hope that it will be useful,
1302+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1303+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1304+ * GNU General Public License for more details.
1305+ *
1306+ * You should have received a copy of the GNU General Public License
1307+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308+ */
1309+
1310+package au.edu.unimelb.csse.mugle.server.api;
1311+
1312+import java.io.Serializable;
1313+
1314+import au.edu.unimelb.csse.mugle.client.api.KeyValueService;
1315+import au.edu.unimelb.csse.mugle.server.PMF;
1316+import au.edu.unimelb.csse.mugle.server.model.KeyValuePairGetter;
1317+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
1318+import au.edu.unimelb.csse.mugle.shared.api.KeyError;
1319+import au.edu.unimelb.csse.mugle.server.model.KeyValuePairData;
1320+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.*;
1321+
1322+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
1323+
1324+import javax.jdo.PersistenceManager;
1325+
1326+/**
1327+ * The server side implementation of KeyValueService.
1328+ */
1329+@SuppressWarnings("serial")
1330+public class KeyValueServiceImpl extends RemoteServiceServlet
1331+ implements KeyValueService
1332+{
1333+ public void put(String gameToken, String key, Serializable value)
1334+ throws GameTokenError
1335+ {
1336+ PersistenceManager pm = PMF.getManager();
1337+ KeyValuePairGetter k = new KeyValuePairGetter();
1338+ KeyValuePairData kvp = null;
1339+
1340+ try {
1341+ kvp = k.getKeyValuePair(pm, key, gameToken, true);
1342+ kvp.setValue(value);
1343+ } catch (UserNotExists e) {
1344+ throw new Error(e);
1345+ } catch (KeyError e) {
1346+ // XXX This should never happen (since we are using createIfNotFound=true)
1347+ throw new Error(e);
1348+ } finally {
1349+ pm.close();
1350+ }
1351+ }
1352+
1353+ public Serializable get(String gameToken, String key)
1354+ throws GameTokenError, KeyError
1355+ {
1356+ KeyValuePairGetter k = new KeyValuePairGetter();
1357+ KeyValuePairData kvp;
1358+ try {
1359+ kvp = k.getKeyValuePair(key, gameToken);
1360+ } catch (UserNotExists e) {
1361+ throw new Error(e);
1362+ }
1363+ return (Serializable) kvp.getValue();
1364+ }
1365+
1366+ public boolean containsKey(String gameToken, String key)
1367+ throws GameTokenError
1368+ {
1369+ KeyValuePairGetter k = new KeyValuePairGetter();
1370+ try {
1371+ k.getKeyValuePair(key, gameToken);
1372+ } catch (UserNotExists e) {
1373+ throw new Error(e);
1374+ } catch (KeyError e) {
1375+ return false;
1376+ }
1377+ return true;
1378+
1379+ }
1380+
1381+}
1382
1383=== added file 'src/au/edu/unimelb/csse/mugle/server/api/UserServiceImpl.java'
1384--- src/au/edu/unimelb/csse/mugle/server/api/UserServiceImpl.java 1970-01-01 00:00:00 +0000
1385+++ src/au/edu/unimelb/csse/mugle/server/api/UserServiceImpl.java 2011-04-16 12:23:28 +0000
1386@@ -0,0 +1,58 @@
1387+/* Melbourne University Game-based Learning Environment
1388+ * Copyright (C) 2011 The University of Melbourne
1389+ *
1390+ * This program is free software: you can redistribute it and/or modify
1391+ * it under the terms of the GNU General Public License as published by
1392+ * the Free Software Foundation, either version 3 of the License, or
1393+ * (at your option) any later version.
1394+ *
1395+ * This program is distributed in the hope that it will be useful,
1396+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1397+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1398+ * GNU General Public License for more details.
1399+ *
1400+ * You should have received a copy of the GNU General Public License
1401+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1402+ */
1403+
1404+package au.edu.unimelb.csse.mugle.server.api;
1405+
1406+import au.edu.unimelb.csse.mugle.client.api.UserService;
1407+import au.edu.unimelb.csse.mugle.server.model.UserGetter;
1408+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserNotExists;
1409+
1410+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
1411+
1412+
1413+/**
1414+ * The server side implementation of KeyValueService.
1415+ */
1416+@SuppressWarnings("serial")
1417+public class UserServiceImpl extends RemoteServiceServlet
1418+ implements UserService
1419+{
1420+
1421+ public String getUserNickName() {
1422+ UserGetter u = new UserGetter();
1423+ try
1424+ {
1425+ return u.getCurrentUser().getUrlName();
1426+ }
1427+ catch (UserNotExists e)
1428+ {
1429+ throw new Error(e);
1430+ }
1431+ }
1432+
1433+ public String getUserID() {
1434+ UserGetter u = new UserGetter();
1435+ try
1436+ {
1437+ return u.getCurrentUser().getGoogleID();
1438+ }
1439+ catch (UserNotExists e)
1440+ {
1441+ throw new Error(e);
1442+ }
1443+ }
1444+}
1445
1446=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/AchievementData.java'
1447--- src/au/edu/unimelb/csse/mugle/server/model/AchievementData.java 2011-04-08 11:00:59 +0000
1448+++ src/au/edu/unimelb/csse/mugle/server/model/AchievementData.java 2011-04-16 12:23:28 +0000
1449@@ -47,6 +47,10 @@
1450 @Persistent
1451 private String name;
1452
1453+ @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="displayName")
1454+ @Persistent
1455+ private String displayName;
1456+
1457 @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="description")
1458 @Persistent
1459 private String description;
1460@@ -71,6 +75,7 @@
1461
1462 this.userAchievements = new HashSet<UserAchievementData>();
1463 this.name = null;
1464+ this.displayName = null;
1465 this.description = null;
1466 this.maxProgress = null;
1467 this.game = null;
1468@@ -79,11 +84,12 @@
1469 }
1470
1471 /* Should only be added through developers interface */
1472- public AchievementData(String name, String description, Integer maxProgress, Game game) {
1473+ public AchievementData(String name, String displayName, String description, Integer maxProgress, Game game) {
1474
1475 this.userAchievements = new HashSet<UserAchievementData>();
1476
1477 this.name = name;
1478+ this.displayName = displayName;
1479 this.description = description;
1480 this.maxProgress = maxProgress;
1481 this.game = game;
1482@@ -101,6 +107,10 @@
1483 public String getName() {
1484 return this.name;
1485 }
1486+
1487+ public String getDisplayName() {
1488+ return displayName;
1489+ }
1490
1491 public String getDescription() {
1492 return this.description;
1493@@ -120,23 +130,27 @@
1494
1495 // Setters
1496
1497- /* Setters are protected - in the case of wanting to change an achievement, better
1498+ /* in the case of wanting to change an achievement, better
1499 * to leave the old ID, so that users dont lose their achievements if they ever need
1500 * updating
1501 */
1502- protected void setName(String newName) {
1503+ public void setName(String newName) {
1504 this.name = newName;
1505 }
1506+
1507+ public void setDisplayName(String displayName) {
1508+ this.displayName = displayName;
1509+ }
1510
1511- protected void setDescription(String newDescription) {
1512+ public void setDescription(String newDescription) {
1513 this.description = newDescription;
1514 }
1515
1516- protected void setMaxProgress(Integer newProgress) {
1517+ public void setMaxProgress(Integer newProgress) {
1518 this.maxProgress = newProgress;
1519 }
1520
1521- protected void setGame(Game game) {
1522+ public void setGame(Game game) {
1523 this.game = game;
1524 }
1525
1526
1527=== added file 'src/au/edu/unimelb/csse/mugle/server/model/AchievementGetter.java'
1528--- src/au/edu/unimelb/csse/mugle/server/model/AchievementGetter.java 1970-01-01 00:00:00 +0000
1529+++ src/au/edu/unimelb/csse/mugle/server/model/AchievementGetter.java 2011-04-16 12:23:28 +0000
1530@@ -0,0 +1,109 @@
1531+/* Melbourne University Game-based Learning Environment
1532+ * Copyright (C) 2011 The University of Melbourne
1533+ *
1534+ * This program is free software: you can redistribute it and/or modify
1535+ * it under the terms of the GNU General Public License as published by
1536+ * the Free Software Foundation, either version 3 of the License, or
1537+ * (at your option) any later version.
1538+ *
1539+ * This program is distributed in the hope that it will be useful,
1540+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1541+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1542+ * GNU General Public License for more details.
1543+ *
1544+ * You should have received a copy of the GNU General Public License
1545+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1546+ */
1547+
1548+package au.edu.unimelb.csse.mugle.server.model;
1549+
1550+import javax.jdo.PersistenceManager;
1551+import javax.jdo.Query;
1552+
1553+import au.edu.unimelb.csse.mugle.server.PMF;
1554+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
1555+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.AchievementNotExists;
1556+
1557+public class AchievementGetter {
1558+
1559+ /**
1560+ * Gets the Achievement of the current game based on its name - READ ONLY
1561+ * @param name Name of the achievement you're looking for
1562+ * @param gameToken the secret game token for the current game, provided by the client
1563+ * @return The requested Achievement - READ ONLY
1564+ * @throws GameTokenError
1565+ * @throws AchievementNotExists
1566+ */
1567+ public AchievementData getAchievement(String name, String gameToken)
1568+ throws GameTokenError, AchievementNotExists {
1569+ PersistenceManager pm = PMF.getManager();
1570+ try {
1571+ return getAchievement(pm, name, gameToken);
1572+ } finally {
1573+ pm.close();
1574+ }
1575+ }
1576+
1577+ /**
1578+ * Gets the Achievement of the current game based on its name, for editing object in datstore
1579+ * The PersistenceManager must be handled by the caller
1580+ * @param pm The Persistence Manager
1581+ * @param name Name of the achievement you're looking for
1582+ * @param gameToken the secret game token for the current game, provided by the client
1583+ * @return The requested Achievement
1584+ * @throws GameTokenError
1585+ * @throws AchievementNotExists
1586+ */
1587+ public AchievementData getAchievement(PersistenceManager pm, String name, String gameToken)
1588+ throws GameTokenError, AchievementNotExists {
1589+ GameGetter g = new GameGetter();
1590+ GameData curGame = g.getCurrentGame(pm, gameToken);
1591+
1592+ Query q = pm.newQuery(AchievementData.class, "game == g && name == n");
1593+ q.declareParameters("GameData g, String n");
1594+ AchievementData achievement = (AchievementData) q.execute(curGame, name);
1595+
1596+ if (achievement == null) {
1597+ throw new AchievementNotExists(curGame.getUrlName(), name);
1598+ }
1599+
1600+ return achievement;
1601+ }
1602+
1603+ /**
1604+ * Gets the Achievement of the current game based on its Primary Key - READ ONLY
1605+ * @param primaryKey the primary key of the Achievement
1606+ * @return The requested Achievement - READ ONLY
1607+ * @throws GameTokenError
1608+ * @throws AchievementNotExists
1609+ */
1610+ public AchievementData getAchievement(Long primaryKey)
1611+ throws GameTokenError, AchievementNotExists {
1612+ PersistenceManager pm = PMF.getManager();
1613+ try {
1614+ return getAchievement(pm, primaryKey);
1615+ } finally {
1616+ pm.close();
1617+ }
1618+ }
1619+
1620+ /**
1621+ * Gets the Achievement of the current game based on its Primary Key, for editing object in datstore
1622+ * The PersistenceManager must be handled by the caller
1623+ * @param pm The Persistence Manager
1624+ * @param primaryKey the primary key of the Achievement
1625+ * @return The requested Achievement
1626+ * @throws GameTokenError
1627+ * @throws AchievementNotExists
1628+ */
1629+ public AchievementData getAchievement(PersistenceManager pm, Long primaryKey)
1630+ throws AchievementNotExists {
1631+ AchievementData achievement = pm.getObjectById(AchievementData.class, primaryKey);
1632+
1633+ if (achievement == null) {
1634+ throw new AchievementNotExists(primaryKey);
1635+ }
1636+
1637+ return achievement;
1638+ }
1639+}
1640
1641=== added file 'src/au/edu/unimelb/csse/mugle/server/model/DevTeamGetter.java'
1642--- src/au/edu/unimelb/csse/mugle/server/model/DevTeamGetter.java 1970-01-01 00:00:00 +0000
1643+++ src/au/edu/unimelb/csse/mugle/server/model/DevTeamGetter.java 2011-04-16 12:23:28 +0000
1644@@ -0,0 +1,78 @@
1645+package au.edu.unimelb.csse.mugle.server.model;
1646+
1647+import javax.jdo.PersistenceManager;
1648+import javax.jdo.Query;
1649+
1650+import au.edu.unimelb.csse.mugle.server.PMF;
1651+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.DevTeamNotExists;
1652+
1653+public class DevTeamGetter {
1654+
1655+ /**
1656+ * Gets the DevTeamData by its urlName - READ ONLY
1657+ * @param name The name of the DevTeamData
1658+ * @return The DevTeamData - READ ONLY
1659+ * @throws DevTeamDataNotExists
1660+ */
1661+ public DevTeamData getDevTeam(String name) throws DevTeamNotExists {
1662+ PersistenceManager pm = PMF.getManager();
1663+ try {
1664+ return getDevTeam(pm, name);
1665+ } finally {
1666+ pm.close();
1667+ }
1668+ }
1669+
1670+ /**
1671+ * Gets the DevTeamData by its urlName, for editing in the datastore
1672+ * The Persistence Manager must be handled by the caller
1673+ * @param pm The PersistenceManager
1674+ * @param name The Name of the Dev Team
1675+ * @return The DevTeamData
1676+ * @throws DevTeamDataNotExists
1677+ */
1678+ public DevTeamData getDevTeam(PersistenceManager pm, String name) throws DevTeamNotExists {
1679+ DevTeamData devTeam= null;
1680+ Query q = pm.newQuery(DevTeamData.class, "urlName == u");
1681+ q.declareParameters("String u");
1682+ devTeam = (DevTeamData) q.execute(name);
1683+
1684+ if (devTeam == null) {
1685+ throw new DevTeamNotExists(name);
1686+ }
1687+
1688+ return devTeam;
1689+ }
1690+ /**
1691+ * Gets the DevTeamDataData by its primary key - READ ONLY
1692+ * @param primaryKey
1693+ * @return The DevTeamDataData - READ ONLY
1694+ * @throws DevTeamDataDataNotExists
1695+ */
1696+ public DevTeamData getDevTeam(Long primaryKey) throws DevTeamNotExists {
1697+ PersistenceManager pm = PMF.getManager();
1698+ try {
1699+ return getDevTeam(pm, primaryKey);
1700+ } finally {
1701+ pm.close();
1702+ }
1703+ }
1704+
1705+ /**
1706+ * Gets the DevTeamDataData by its primary key, for editing in the datastore
1707+ * The Persistence Manager must be handled by the caller
1708+ * @param pm The PersistenceManager
1709+ * @param primaryKey
1710+ * @return The DevTeamDataData
1711+ * @throws DevTeamDataDataNotExists
1712+ */
1713+ public DevTeamData getDevTeam(PersistenceManager pm, Long primaryKey) throws DevTeamNotExists {
1714+ DevTeamData devTeam = pm.getObjectById(DevTeamData.class, primaryKey);
1715+
1716+ if (devTeam == null) {
1717+ throw new DevTeamNotExists(primaryKey);
1718+ }
1719+
1720+ return devTeam;
1721+ }
1722+}
1723
1724=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/GameData.java'
1725--- src/au/edu/unimelb/csse/mugle/server/model/GameData.java 2011-04-08 11:00:59 +0000
1726+++ src/au/edu/unimelb/csse/mugle/server/model/GameData.java 2011-04-16 12:23:28 +0000
1727@@ -48,6 +48,10 @@
1728 @Persistent
1729 private String urlName; //Must be unique
1730
1731+ @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="gameToken")
1732+ @Persistent
1733+ private String gameToken;
1734+
1735 @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="userRating")
1736 @Persistent
1737 private Integer userRating;
1738@@ -82,6 +86,7 @@
1739 this.gameVersions = new HashSet<GameVersionData>();
1740 this.ugps = new HashSet<Key>();
1741 this.achievements = new HashSet<AchievementData>();
1742+ this.gameToken = null;
1743 this.urlName = null;
1744 this.userRating = null;
1745 this.totalRatings = null;
1746@@ -95,7 +100,9 @@
1747 this.ugps = new HashSet<Key>();
1748 this.achievements = new HashSet<AchievementData>();
1749
1750- //TODO: check that urlName is unique
1751+ //TODO: generate a gameToken
1752+ this.gameToken = null;
1753+ //TODO: check that urlName is unique
1754 this.urlName = urlName;
1755 this.userRating = 0;
1756 this.totalRatings = 0;
1757@@ -137,6 +144,10 @@
1758 public Set<Key> getUserGameProfiles() {
1759 return this.ugps;
1760 }
1761+
1762+ public String getGameToken() {
1763+ return gameToken;
1764+ }
1765
1766
1767 // Setters
1768
1769=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/GameFileData.java'
1770--- src/au/edu/unimelb/csse/mugle/server/model/GameFileData.java 2011-04-08 11:00:59 +0000
1771+++ src/au/edu/unimelb/csse/mugle/server/model/GameFileData.java 2011-04-16 12:23:28 +0000
1772@@ -25,6 +25,7 @@
1773 import javax.jdo.annotations.Persistent;
1774 import javax.jdo.annotations.PrimaryKey;
1775
1776+import com.google.appengine.api.blobstore.BlobKey;
1777 import com.google.appengine.api.datastore.Key;
1778
1779 import au.edu.unimelb.csse.mugle.shared.model.*;
1780@@ -47,8 +48,14 @@
1781 @Persistent
1782 private String path; //path to the file relative to the Game URL
1783
1784- // TODO: data (blob)
1785+ @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="mimeType")
1786+ @Persistent
1787+ private String mimeType; //mime type of the file
1788
1789+ @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, useMethod=true, mappedBy="getBlobKeyString")
1790+ @Persistent
1791+ private BlobKey blobKey; //key to the actual blob
1792+
1793 // Many-to-many
1794 @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, useMethod=true, mappedBy="keysToGameVersions")
1795 @Persistent
1796@@ -58,6 +65,8 @@
1797 // Constructors
1798 public GameFileData() {
1799 this.versions = new HashSet<Key>();
1800+ this.setMimeType(null);
1801+ this.setBlobKey(null);
1802 this.path = null;
1803 }
1804
1805@@ -179,4 +188,24 @@
1806 return this.fetchClientObjects(GameVersionData.class, this.versions);
1807 }
1808
1809+ public String getBlobKeyString() {
1810+ return this.blobKey.getKeyString();
1811+ }
1812+
1813+ public void setMimeType(String mimeType) {
1814+ this.mimeType = mimeType;
1815+ }
1816+
1817+ public String getMimeType() {
1818+ return mimeType;
1819+ }
1820+
1821+ public void setBlobKey(BlobKey blobKey) {
1822+ this.blobKey = blobKey;
1823+ }
1824+
1825+ public BlobKey getBlobKey() {
1826+ return blobKey;
1827+ }
1828+
1829 }
1830
1831=== added file 'src/au/edu/unimelb/csse/mugle/server/model/GameGetter.java'
1832--- src/au/edu/unimelb/csse/mugle/server/model/GameGetter.java 1970-01-01 00:00:00 +0000
1833+++ src/au/edu/unimelb/csse/mugle/server/model/GameGetter.java 2011-04-16 12:23:28 +0000
1834@@ -0,0 +1,132 @@
1835+/* Melbourne University Game-based Learning Environment
1836+ * Copyright (C) 2011 The University of Melbourne
1837+ *
1838+ * This program is free software: you can redistribute it and/or modify
1839+ * it under the terms of the GNU General Public License as published by
1840+ * the Free Software Foundation, either version 3 of the License, or
1841+ * (at your option) any later version.
1842+ *
1843+ * This program is distributed in the hope that it will be useful,
1844+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1845+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1846+ * GNU General Public License for more details.
1847+ *
1848+ * You should have received a copy of the GNU General Public License
1849+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1850+ */
1851+
1852+package au.edu.unimelb.csse.mugle.server.model;
1853+
1854+import javax.jdo.PersistenceManager;
1855+import javax.jdo.Query;
1856+
1857+import au.edu.unimelb.csse.mugle.server.PMF;
1858+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
1859+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.GameNotExists;
1860+
1861+public class GameGetter {
1862+ /**
1863+ * Gets the Game by its Primary Key - READ ONLY
1864+ * @param primaryKey
1865+ * @return the Game - read only
1866+ * @throws GameNotExists
1867+ */
1868+ public GameData getGame(Long primaryKey) throws GameNotExists {
1869+ PersistenceManager pm = PMF.getManager();
1870+ try {
1871+ return getGame(pm, primaryKey);
1872+ } finally {
1873+ pm.close();
1874+ }
1875+ }
1876+
1877+ /**
1878+ * Gets the Game by its Primary Key, for editing object in datstore
1879+ * PersistenceManager must be handled by the caller
1880+ * @param pm the PersistenceManager
1881+ * @param primaryKey
1882+ * @return the Game
1883+ * @throws GameNotExists
1884+ */
1885+ public GameData getGame(PersistenceManager pm, Long primaryKey) throws GameNotExists{
1886+ GameData game = pm.getObjectById(GameData.class, primaryKey);
1887+
1888+ if(game == null) {
1889+ throw new GameNotExists(primaryKey);
1890+ }
1891+
1892+ return game;
1893+ }
1894+
1895+ /**
1896+ * Gets the Game by its name - READ ONLY
1897+ * @param name
1898+ * @return the Game - read only
1899+ * @throws GameNotExists
1900+ */
1901+ public GameData getGame(String name) throws GameNotExists {
1902+ PersistenceManager pm = PMF.getManager();
1903+ try {
1904+ return getGame(pm, name);
1905+ } finally {
1906+ pm.close();
1907+ }
1908+ }
1909+
1910+ /**
1911+ * Gets the Game by name, for editing object in datstore
1912+ * PersistenceManager must be handled by the caller
1913+ * @param pm the PersistenceManager
1914+ * @param name
1915+ * @return the Game
1916+ * @throws GameNotExists
1917+ */
1918+ public GameData getGame(PersistenceManager pm, String name) throws GameNotExists{
1919+ GameData game = null;
1920+ Query q = pm.newQuery(GameData.class, "urlName == u");
1921+ q.declareParameters("String u");
1922+ game = (GameData) q.execute(name);
1923+
1924+ if(game == null) {
1925+ throw new GameNotExists(name);
1926+ }
1927+
1928+ return game;
1929+ }
1930+
1931+ /**
1932+ * Gets the Game from a provided gameToken - READ ONLY
1933+ * @param gameToken the secret game token for the current game, provided by the client
1934+ * @return the Game - read only
1935+ * @throws GameTokenError
1936+ */
1937+ public GameData getCurrentGame(String gameToken) throws GameTokenError {
1938+ PersistenceManager pm = PMF.getManager();
1939+ try {
1940+ return getCurrentGame(pm, gameToken);
1941+ } finally {
1942+ pm.close();
1943+ }
1944+ }
1945+
1946+ /**
1947+ * Gets the Game from a provided gameToken, for editing object in datstore
1948+ * PersistenceManager must be handled by the caller
1949+ * @param pm the PersistenceManager
1950+ * @param gameToken the secret game token for the current game, provided by the client
1951+ * @return the Game
1952+ * @throws GameTokenError
1953+ */
1954+ public GameData getCurrentGame(PersistenceManager pm, String gameToken) throws GameTokenError {
1955+ GameData curGame = null;
1956+ Query q = pm.newQuery(GameData.class, "gameToken == g");
1957+ q.declareParameters("String g");
1958+ curGame = (GameData) q.execute(gameToken);
1959+
1960+ if(curGame == null) {
1961+ throw new GameTokenError(gameToken);
1962+ }
1963+
1964+ return curGame;
1965+ }
1966+}
1967
1968=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairData.java'
1969--- src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairData.java 2011-03-31 09:56:28 +0000
1970+++ src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairData.java 2011-04-16 12:23:28 +0000
1971@@ -109,6 +109,10 @@
1972 this.value = value;
1973 }
1974
1975+ public void setUserGameProfile(UserGameProfileData ugp) {
1976+ this.ugp = ugp;
1977+ }
1978+
1979 @Override
1980 public Key getServerKey() {
1981 return this.id;
1982@@ -132,4 +136,6 @@
1983 return KeyValuePair.class;
1984 }
1985
1986+
1987+
1988 }
1989
1990=== added file 'src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairGetter.java'
1991--- src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairGetter.java 1970-01-01 00:00:00 +0000
1992+++ src/au/edu/unimelb/csse/mugle/server/model/KeyValuePairGetter.java 2011-04-16 12:23:28 +0000
1993@@ -0,0 +1,108 @@
1994+/* Melbourne University Game-based Learning Environment
1995+ * Copyright (C) 2011 The University of Melbourne
1996+ *
1997+ * This program is free software: you can redistribute it and/or modify
1998+ * it under the terms of the GNU General Public License as published by
1999+ * the Free Software Foundation, either version 3 of the License, or
2000+ * (at your option) any later version.
2001+ *
2002+ * This program is distributed in the hope that it will be useful,
2003+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2004+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2005+ * GNU General Public License for more details.
2006+ *
2007+ * You should have received a copy of the GNU General Public License
2008+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2009+ */
2010+package au.edu.unimelb.csse.mugle.server.model;
2011+
2012+import javax.jdo.PersistenceManager;
2013+import javax.jdo.Query;
2014+
2015+import au.edu.unimelb.csse.mugle.server.PMF;
2016+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
2017+import au.edu.unimelb.csse.mugle.shared.api.KeyError;
2018+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserNotExists;
2019+
2020+public class KeyValuePairGetter {
2021+
2022+ /**
2023+ * Gets the KeyValuePair for the key provided from the datastore for the
2024+ * player currently playing - READ ONLY
2025+ * @param key the key to look up of the KeyValuePair
2026+ * @param gameToken the secret game token for the current game, provided by the client
2027+ * @return The request KeyValuePair - READ ONLY
2028+ * @throws UserNotExists
2029+ * @throws GameTokenError
2030+ * @throws KeyError
2031+ */
2032+ public KeyValuePairData getKeyValuePair(String key, String gameToken)
2033+ throws UserNotExists, GameTokenError, KeyError {
2034+ PersistenceManager pm = PMF.getManager();
2035+ try {
2036+ return getKeyValuePair(pm, key, gameToken);
2037+ } finally {
2038+ pm.close();
2039+ }
2040+ }
2041+
2042+
2043+ /**
2044+ * Gets the KeyValuePair for the key provided from the datastore for the
2045+ * player currently playing, for editing object in datastore
2046+ * The Persistence Manager must be handled by the caller
2047+ * @param pm The PersistenceManager
2048+ * @param key the key to look up of the KeyValuePair
2049+ * @param gameToken the secret game token for the current game, provided by the client
2050+ * @return The request KeyValuePair
2051+ * @throws UserNotExists
2052+ * @throws GameTokenError
2053+ * @throws KeyError
2054+ */
2055+ public KeyValuePairData getKeyValuePair(PersistenceManager pm, String key, String gameToken)
2056+ throws UserNotExists, GameTokenError, KeyError {
2057+ return getKeyValuePair(pm, key, gameToken, false);
2058+ }
2059+
2060+ /**
2061+ * Gets the KeyValuePair for the key provided from the datastore for the
2062+ * player currently playing, for editing object in datastore - if the KeyValuePair isnt
2063+ * found the parameter createIfNotFound determines whether an exception will be thrown, or
2064+ * if a new KeyValuePair is created and associated to that User's UserGameProfile
2065+ * The Persistence Manager must be handled by the caller
2066+ * @param pm The PersistenceManager
2067+ * @param key the key to look up of the KeyValuePair
2068+ * @param gameToken the secret game token for the current game, provided by the client
2069+ * @param createIfNotFound boolean to determine whether a new KeyValuePair is created if its not found.s
2070+ * @return The request KeyValuePair
2071+ * @throws UserNotExists
2072+ * @throws GameTokenError
2073+ * @throws KeyError
2074+ */
2075+ public KeyValuePairData getKeyValuePair(PersistenceManager pm, String key, String gameToken, boolean createIfNotFound)
2076+ throws UserNotExists, GameTokenError, KeyError {
2077+ UserGameProfileGetter u = new UserGameProfileGetter();
2078+ UserGameProfileData ugp = u.getCurrentUserGameProfile(pm, gameToken);
2079+
2080+ KeyValuePairData kvp = null;
2081+
2082+ Query q = pm.newQuery(KeyValuePairData.class, "key == k && ugp == u");
2083+ q.declareParameters("String k, UserGameProfileData u");
2084+ kvp = (KeyValuePairData) q.execute(key, ugp);
2085+
2086+ /* If the key value pair isn't found - we want to create one if
2087+ * createIfNotFound is set to true
2088+ */
2089+ if (kvp == null) {
2090+ if (createIfNotFound) {
2091+ kvp = new KeyValuePairData();
2092+ kvp.setKey(key);
2093+ kvp.setUserGameProfile(ugp);
2094+ } else {
2095+ throw new KeyError(key);
2096+ }
2097+ }
2098+
2099+ return kvp;
2100+ }
2101+}
2102
2103=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/ModelDataClass.java'
2104--- src/au/edu/unimelb/csse/mugle/server/model/ModelDataClass.java 2011-04-08 11:00:59 +0000
2105+++ src/au/edu/unimelb/csse/mugle/server/model/ModelDataClass.java 2011-04-16 12:23:28 +0000
2106@@ -24,7 +24,7 @@
2107
2108 import com.google.appengine.api.datastore.Key;
2109
2110-import au.edu.unimelb.csse.mugle.server.platform.PMF;
2111+import au.edu.unimelb.csse.mugle.server.PMF;
2112 import au.edu.unimelb.csse.mugle.shared.model.ModelClass;
2113
2114 /**
2115
2116=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/ModelWrapper.java'
2117--- src/au/edu/unimelb/csse/mugle/server/model/ModelWrapper.java 2011-04-08 11:00:59 +0000
2118+++ src/au/edu/unimelb/csse/mugle/server/model/ModelWrapper.java 2011-04-16 12:23:28 +0000
2119@@ -22,7 +22,7 @@
2120 import javax.jdo.PersistenceManager;
2121
2122 import au.edu.unimelb.csse.mugle.server.model.annotations.*;
2123-import au.edu.unimelb.csse.mugle.server.platform.PMF;
2124+import au.edu.unimelb.csse.mugle.server.PMF;
2125 import au.edu.unimelb.csse.mugle.shared.model.*;
2126 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
2127 import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserPrivilegeException;
2128
2129=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/UserAchievementData.java'
2130--- src/au/edu/unimelb/csse/mugle/server/model/UserAchievementData.java 2011-03-31 09:56:28 +0000
2131+++ src/au/edu/unimelb/csse/mugle/server/model/UserAchievementData.java 2011-04-16 12:23:28 +0000
2132@@ -73,7 +73,7 @@
2133 this.ugp = ugp;
2134 this.achievement = achievement;
2135 this.achieved = true;
2136- this.progress = 1; //default assume 1/1
2137+ this.progress = 0;
2138 }
2139
2140 //Constructor for achievements with progress
2141@@ -136,15 +136,21 @@
2142
2143 // Misc methods
2144
2145- public void addProgress(int additionalProgress) {
2146+ public boolean addProgress(int additionalProgress) {
2147 /*If the progress is greater or equal to the max progress of the achievement,
2148 * set it to be achieved, and set the progress to maxProgress
2149 */
2150- if (this.progress + additionalProgress >= this.achievement.getMaxProgress()) {
2151- this.progress = this.achievement.getMaxProgress();
2152+ int maxProgress = this.achievement.getMaxProgress();
2153+ int prog = this.progress + additionalProgress;
2154+
2155+ if (prog >= maxProgress) {
2156+ this.progress = maxProgress;
2157 this.achieved = true;
2158+ return true;
2159 } else {
2160- this.progress += additionalProgress;
2161+ this.progress = prog;
2162+ this.achieved = false; // If for some reason, they change the max progress to be less.
2163+ return false;
2164 }
2165 }
2166
2167
2168=== added file 'src/au/edu/unimelb/csse/mugle/server/model/UserAchievementGetter.java'
2169--- src/au/edu/unimelb/csse/mugle/server/model/UserAchievementGetter.java 1970-01-01 00:00:00 +0000
2170+++ src/au/edu/unimelb/csse/mugle/server/model/UserAchievementGetter.java 2011-04-16 12:23:28 +0000
2171@@ -0,0 +1,84 @@
2172+/* Melbourne University Game-based Learning Environment
2173+ * Copyright (C) 2011 The University of Melbourne
2174+ *
2175+ * This program is free software: you can redistribute it and/or modify
2176+ * it under the terms of the GNU General Public License as published by
2177+ * the Free Software Foundation, either version 3 of the License, or
2178+ * (at your option) any later version.
2179+ *
2180+ * This program is distributed in the hope that it will be useful,
2181+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2182+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2183+ * GNU General Public License for more details.
2184+ *
2185+ * You should have received a copy of the GNU General Public License
2186+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2187+ */
2188+
2189+package au.edu.unimelb.csse.mugle.server.model;
2190+
2191+import javax.jdo.PersistenceManager;
2192+import javax.jdo.Query;
2193+
2194+import au.edu.unimelb.csse.mugle.server.PMF;
2195+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
2196+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.AchievementNotExists;
2197+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserNotExists;
2198+
2199+public class UserAchievementGetter {
2200+ /**
2201+ * Gets the UserAchievement for the requested achievement of the user currently
2202+ * playing the current game - READ ONLY
2203+ * @param achievementName the name of the achievement requested
2204+ * @param gameToken the secret game token for the current game, provided by the client
2205+ * @return The UserAchievement - READ ONLY
2206+ * @throws UserNotExists
2207+ * @throws GameTokenError
2208+ * @throws AchievementNotExists
2209+ */
2210+ public UserAchievementData getUserAchievement(String achievementName, String gameToken)
2211+ throws UserNotExists, GameTokenError, AchievementNotExists {
2212+ PersistenceManager pm = PMF.getManager();
2213+ try {
2214+ return getUserAchievement(pm, achievementName, gameToken);
2215+ } finally {
2216+ pm.close();
2217+ }
2218+ }
2219+
2220+ /**
2221+ * Gets the UserAchievement for the requested achievement of the user currently
2222+ * playing the current game, for editing object in datastore
2223+ * The PersistenceManager must be handled by the caller
2224+ * @param pm the Persistence Manager
2225+ * @param achievementName the name of the achievement requested
2226+ * @param gameToken the secret game token for the current game, provided by the client
2227+ * @return The UserAchievement
2228+ * @throws UserNotExists
2229+ * @throws GameTokenError
2230+ * @throws AchievementNotExists
2231+ */
2232+ public UserAchievementData getUserAchievement(PersistenceManager pm, String achievementName, String gameToken)
2233+ throws UserNotExists, GameTokenError, AchievementNotExists {
2234+ UserGameProfileGetter u = new UserGameProfileGetter();
2235+ AchievementGetter a = new AchievementGetter();
2236+
2237+ UserGameProfileData ugp = u.getCurrentUserGameProfile(pm, gameToken);
2238+ AchievementData achievement = a.getAchievement(pm, achievementName, gameToken);
2239+
2240+ Query q = pm.newQuery(UserAchievementData.class, "ugp == u && achievement == a");
2241+ q.declareParameters("UserGameProfileData ugp, AchievementData a");
2242+ UserAchievementData ua = (UserAchievementData) q.execute(ugp, achievement);
2243+
2244+ /* If we can't find the UserAchievement it makes sense to create one
2245+ * if the UserGameProfile and the Achievement exist.
2246+ */
2247+ if (ua == null) {
2248+ ua = new UserAchievementData();
2249+ ua.setAchievement(achievement);
2250+ ua.setUserGameProfile(ugp);
2251+ }
2252+
2253+ return ua;
2254+ }
2255+}
2256
2257=== modified file 'src/au/edu/unimelb/csse/mugle/server/model/UserData.java'
2258--- src/au/edu/unimelb/csse/mugle/server/model/UserData.java 2011-04-08 11:00:59 +0000
2259+++ src/au/edu/unimelb/csse/mugle/server/model/UserData.java 2011-04-16 12:23:28 +0000
2260@@ -42,6 +42,10 @@
2261 @PrimaryKey
2262 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
2263 private Key id;
2264+
2265+ @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="googleID")
2266+ @Persistent
2267+ private String googleID; //Unique userID provided by google
2268
2269 @UserLevel(privateView=Role.DEVELOPER, publicView=Role.DEVELOPER, mappedBy="urlName")
2270 @Persistent
2271@@ -80,6 +84,7 @@
2272
2273 this.devTeams = new HashSet<Key>();
2274 this.ugps = new HashSet<Key>();
2275+ this.googleID = null;
2276 this.urlName = null;
2277 this.fullName = null;
2278 this.email = null;
2279@@ -95,6 +100,7 @@
2280
2281 this.urlName = url_name;
2282 this.fullName = full_name;
2283+ this.googleID = null;
2284 //TODO: check that email is unique and valid.
2285 this.email = email;
2286 this.role = role;
2287@@ -112,6 +118,10 @@
2288 public String getUrlName() {
2289 return this.urlName;
2290 }
2291+
2292+ public String getGoogleID() {
2293+ return googleID;
2294+ }
2295
2296 public String getFullName() {
2297 return this.fullName;
2298@@ -147,6 +157,10 @@
2299 //TODO: check that newName is unique.
2300 this.urlName = newName;
2301 }
2302+
2303+ public void setGoogleID(String googleID) {
2304+ this.googleID = googleID;
2305+ }
2306
2307 /* This can only be changed by an Admin, again we need an Admin control panel */
2308 public void setRole(Role newRole) {
2309
2310=== added file 'src/au/edu/unimelb/csse/mugle/server/model/UserGameProfileGetter.java'
2311--- src/au/edu/unimelb/csse/mugle/server/model/UserGameProfileGetter.java 1970-01-01 00:00:00 +0000
2312+++ src/au/edu/unimelb/csse/mugle/server/model/UserGameProfileGetter.java 2011-04-16 12:23:28 +0000
2313@@ -0,0 +1,113 @@
2314+/* Melbourne University Game-based Learning Environment
2315+ * Copyright (C) 2011 The University of Melbourne
2316+ *
2317+ * This program is free software: you can redistribute it and/or modify
2318+ * it under the terms of the GNU General Public License as published by
2319+ * the Free Software Foundation, either version 3 of the License, or
2320+ * (at your option) any later version.
2321+ *
2322+ * This program is distributed in the hope that it will be useful,
2323+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2324+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2325+ * GNU General Public License for more details.
2326+ *
2327+ * You should have received a copy of the GNU General Public License
2328+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2329+ */
2330+
2331+package au.edu.unimelb.csse.mugle.server.model;
2332+
2333+import javax.jdo.PersistenceManager;
2334+import javax.jdo.Query;
2335+
2336+import au.edu.unimelb.csse.mugle.server.PMF;
2337+import au.edu.unimelb.csse.mugle.shared.api.GameTokenError;
2338+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserGameProfileNotExists;
2339+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserNotExists;
2340+
2341+public class UserGameProfileGetter {
2342+ /**
2343+ * Gets the UserGameProfile by its Primary Key - READ ONLY
2344+ * @param primaryKey
2345+ * @return The UserGameProfile - READ ONLY
2346+ * @throws UserGameProfileNotExists
2347+ */
2348+ public UserGameProfileData getUserGameProfile(Long primaryKey)
2349+ throws UserGameProfileNotExists {
2350+ PersistenceManager pm = PMF.getManager();
2351+ try {
2352+ return getUserGameProfile(pm, primaryKey);
2353+ } finally {
2354+ pm.close();
2355+ }
2356+ }
2357+
2358+ /**
2359+ * Gets the UserGameProfile by its Primary Key, for editing the object in the datastore
2360+ * PersistenceManager must be handled by the caller
2361+ * @param pm The PersistenceManager
2362+ * @param primaryKey
2363+ * @return The UserGameProfile
2364+ * @throws UserGameProfileNotExists
2365+ */
2366+ public UserGameProfileData getUserGameProfile(PersistenceManager pm, Long primaryKey)
2367+ throws UserGameProfileNotExists {
2368+ UserGameProfileData ugp = pm.getObjectById(UserGameProfileData.class, primaryKey);
2369+
2370+ if (ugp == null) {
2371+ throw new UserGameProfileNotExists(primaryKey);
2372+ }
2373+ return ugp;
2374+ }
2375+
2376+ /**
2377+ * Gets the UserGameProfile of the current user based on the game they're playing (read only)
2378+ * @param gameToken the secret game token for the current game, provided by the client
2379+ * @return the UserGameProfile - READ ONLY
2380+ * @throws UserNotExists
2381+ * @throws GameTokenError
2382+ */
2383+ public UserGameProfileData getCurrentUserGameProfile(String gameToken)
2384+ throws UserNotExists, GameTokenError {
2385+ PersistenceManager pm = PMF.getManager();
2386+ try {
2387+ return getCurrentUserGameProfile(pm, gameToken);
2388+ } finally {
2389+ pm.close();
2390+ }
2391+ }
2392+
2393+ /**
2394+ * Gets the UserGameProfile of the current user based on the game they're playing,
2395+ * for editing object in datstore
2396+ * The Persistence Manager must be handled by the caller
2397+ * @param pm The Persistence Manager
2398+ * @param gameToken the secret game token for the current game, provided by the client
2399+ * @return The UserGameProfile of the current user / game.
2400+ * @throws UserNotExists
2401+ * @throws GameTokenError
2402+ */
2403+ public UserGameProfileData getCurrentUserGameProfile(PersistenceManager pm, String gameToken)
2404+ throws UserNotExists, GameTokenError {
2405+ UserGetter u = new UserGetter();
2406+ GameGetter g = new GameGetter();
2407+ UserData curUser = u.getCurrentUser(pm);
2408+ GameData curGame = g.getCurrentGame(pm, gameToken);
2409+ UserGameProfileData ugp = null;
2410+
2411+ Query q = pm.newQuery(UserGameProfileData.class, "user == u && game == g");
2412+ q.declareParameters("UserData u, GameData g");
2413+ ugp = (UserGameProfileData) q.execute(curUser, curGame);
2414+
2415+ /* If we can't find the UserGameProfile it makes sense to create one
2416+ * if the user is playing the game
2417+ */
2418+ if (ugp == null) {
2419+ ugp = new UserGameProfileData();
2420+ ugp.setGame(curGame);
2421+ ugp.setUser(curUser);
2422+ }
2423+ return ugp;
2424+ }
2425+
2426+}
2427
2428=== added file 'src/au/edu/unimelb/csse/mugle/server/model/UserGetter.java'
2429--- src/au/edu/unimelb/csse/mugle/server/model/UserGetter.java 1970-01-01 00:00:00 +0000
2430+++ src/au/edu/unimelb/csse/mugle/server/model/UserGetter.java 2011-04-16 12:23:28 +0000
2431@@ -0,0 +1,160 @@
2432+/* Melbourne University Game-based Learning Environment
2433+ * Copyright (C) 2011 The University of Melbourne
2434+ *
2435+ * This program is free software: you can redistribute it and/or modify
2436+ * it under the terms of the GNU General Public License as published by
2437+ * the Free Software Foundation, either version 3 of the License, or
2438+ * (at your option) any later version.
2439+ *
2440+ * This program is distributed in the hope that it will be useful,
2441+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2442+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2443+ * GNU General Public License for more details.
2444+ *
2445+ * You should have received a copy of the GNU General Public License
2446+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2447+ */
2448+
2449+package au.edu.unimelb.csse.mugle.server.model;
2450+
2451+import javax.jdo.PersistenceManager;
2452+import javax.jdo.Query;
2453+
2454+import au.edu.unimelb.csse.mugle.client.LoginInfo;
2455+import au.edu.unimelb.csse.mugle.server.LoginServiceImpl;
2456+import au.edu.unimelb.csse.mugle.server.PMF;
2457+import au.edu.unimelb.csse.mugle.shared.platform.exceptions.UserNotExists;
2458+
2459+public class UserGetter {
2460+
2461+ /**
2462+ * Gets a User based on the Primary Key
2463+ * @param primaryKey
2464+ * @return The User class - READ ONLY
2465+ * @throws UserNotExists
2466+ */
2467+ public UserData getUser(Long primaryKey) throws UserNotExists {
2468+ PersistenceManager pm = PMF.getManager();
2469+ try {
2470+ return getUser(pm, primaryKey);
2471+ } finally {
2472+ pm.close();
2473+ }
2474+ }
2475+
2476+ /**
2477+ * Gets a User based on their Primary Key, for editing object in datstore
2478+ * Persistence Manager must be handle by caller
2479+ * @param pm The Persistence Manager
2480+ * @param primaryKey
2481+ * @return The User class
2482+ * @throws UserNotExists
2483+ */
2484+ public UserData getUser(PersistenceManager pm, Long primaryKey) throws UserNotExists {
2485+ UserData u = pm.getObjectById(UserData.class, primaryKey);
2486+
2487+ if (u == null) {
2488+ throw new UserNotExists(primaryKey);
2489+ }
2490+
2491+ return u;
2492+ }
2493+ /**
2494+ * Gets a User based on their urlName - READ ONLY
2495+ * @param name
2496+ * @return The User class - READ ONLY
2497+ * @throws UserNotExists
2498+ */
2499+ public UserData getUserByName(String name) throws UserNotExists {
2500+ PersistenceManager pm = PMF.getManager();
2501+ try {
2502+ return getUserByName(pm, name);
2503+ } finally {
2504+ pm.close();
2505+ }
2506+ }
2507+
2508+ /**
2509+ * Gets a User based on their urlName, for editing object in datstore
2510+ * Persistence Manager must be handle by caller
2511+ * @param pm The Persistence Manager
2512+ * @param name
2513+ * @return The User class
2514+ * @throws UserNotExists
2515+ */
2516+ public UserData getUserByName(PersistenceManager pm, String name) throws UserNotExists {
2517+ Query q = pm.newQuery(UserData.class, "urlName == u");
2518+ q.declareParameters("String u");
2519+ UserData u = (UserData) q.execute(name);
2520+
2521+ if (u == null) {
2522+ throw new UserNotExists(name);
2523+ }
2524+
2525+ return u;
2526+ }
2527+
2528+ /**
2529+ * Gets a User based on their unique google ID - READ ONLY
2530+ * @param googleID
2531+ * @return The User class - READ ONLY
2532+ * @throws UserNotExists
2533+ */
2534+ public UserData getUser(String googleID) throws UserNotExists {
2535+ PersistenceManager pm = PMF.getManager();
2536+ try {
2537+ return getUser(pm, googleID);
2538+ } finally {
2539+ pm.close();
2540+ }
2541+ }
2542+
2543+ /**
2544+ * Gets a User based on their unique google ID, for editing object in datstore
2545+ * Persistence Manager must be handle by caller
2546+ * @param pm The Persistence Manager
2547+ * @param googleID
2548+ * @return The User class
2549+ * @throws UserNotExists
2550+ */
2551+ public UserData getUser(PersistenceManager pm, String googleID) throws UserNotExists {
2552+ Query q = pm.newQuery(UserData.class, "googleID == u");
2553+ q.declareParameters("String u");
2554+ UserData u = (UserData) q.execute(googleID);
2555+
2556+ if (u == null) {
2557+ throw new UserNotExists(googleID);
2558+ }
2559+
2560+ return u;
2561+ }
2562+
2563+ /**
2564+ * Gets the currently logged in User - READ ONLY
2565+ * @return the User - read only
2566+ * @throws UserNotExists
2567+ */
2568+ public UserData getCurrentUser() throws UserNotExists {
2569+ PersistenceManager pm = PMF.getManager();
2570+ try {
2571+ return getCurrentUser(pm);
2572+ } finally {
2573+ pm.close();
2574+ }
2575+ }
2576+
2577+ /**
2578+ * Gets the currently logged in User, for editing object in datstore
2579+ * Persistence Manager must be handled by the caller
2580+ * @param pm The Persistence Manager
2581+ * @return the current User
2582+ * @throws UserNotExists
2583+ */
2584+ public UserData getCurrentUser(PersistenceManager pm) throws UserNotExists {
2585+ LoginServiceImpl loginService = new LoginServiceImpl();
2586+ LoginInfo loginInfo = loginService.getCurrentUser();
2587+
2588+ return getUser(pm, loginInfo.getUserID());
2589+ }
2590+
2591+}
2592
2593=== modified file 'src/au/edu/unimelb/csse/mugle/server/platform/AdminServiceImpl.java'
2594--- src/au/edu/unimelb/csse/mugle/server/platform/AdminServiceImpl.java 2011-03-30 15:46:59 +0000
2595+++ src/au/edu/unimelb/csse/mugle/server/platform/AdminServiceImpl.java 2011-04-16 12:23:28 +0000
2596@@ -22,6 +22,7 @@
2597 import au.edu.unimelb.csse.mugle.shared.model.*;
2598 import au.edu.unimelb.csse.mugle.shared.platform.exceptions.*;
2599
2600+@SuppressWarnings("serial")
2601 public class AdminServiceImpl extends DeveloperServiceImpl implements AdminService {
2602
2603 @Override
2604
2605=== modified file 'src/au/edu/unimelb/csse/mugle/server/platform/DeveloperServiceImpl.java'
2606--- src/au/edu/unimelb/csse/mugle/server/platform/DeveloperServiceImpl.java 2011-03-30 15:46:59 +0000
2607+++ src/au/edu/unimelb/csse/mugle/server/platform/DeveloperServiceImpl.java 2011-04-16 12:23:28 +0000
2608@@ -22,6 +22,7 @@
2609 import au.edu.unimelb.csse.mugle.shared.model.*;
2610 import au.edu.unimelb.csse.mugle.shared.platform.exceptions.*;
2611
2612+@SuppressWarnings("serial")
2613 public class DeveloperServiceImpl extends UserServiceImpl implements DeveloperService {
2614
2615 @Override
2616
2617=== modified file 'src/au/edu/unimelb/csse/mugle/server/platform/ServiceHelper.java'
2618--- src/au/edu/unimelb/csse/mugle/server/platform/ServiceHelper.java 2011-03-30 15:46:59 +0000
2619+++ src/au/edu/unimelb/csse/mugle/server/platform/ServiceHelper.java 2011-04-16 12:23:28 +0000
2620@@ -25,6 +25,7 @@
2621 import com.google.appengine.api.datastore.Query;
2622 import com.google.appengine.api.datastore.Query.FilterOperator;
2623
2624+import au.edu.unimelb.csse.mugle.server.PMF;
2625 import au.edu.unimelb.csse.mugle.server.model.*;
2626 import au.edu.unimelb.csse.mugle.shared.model.*;
2627 import au.edu.unimelb.csse.mugle.shared.platform.exceptions.*;
2628
2629=== added directory 'src/au/edu/unimelb/csse/mugle/shared/api'
2630=== added file 'src/au/edu/unimelb/csse/mugle/shared/api/Badge.java'
2631--- src/au/edu/unimelb/csse/mugle/shared/api/Badge.java 1970-01-01 00:00:00 +0000
2632+++ src/au/edu/unimelb/csse/mugle/shared/api/Badge.java 2011-04-16 12:23:28 +0000
2633@@ -0,0 +1,85 @@
2634+/* Melbourne University Game-based Learning Environment
2635+ * Copyright (C) 2011 The University of Melbourne
2636+ *
2637+ * This program is free software: you can redistribute it and/or modify
2638+ * it under the terms of the GNU Lesser General Public License as published
2639+ * by the Free Software Foundation, either version 3 of the License, or
2640+ * (at your option) any later version.
2641+ *
2642+ * This program is distributed in the hope that it will be useful,
2643+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2644+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2645+ * GNU Lesser General Public License for more details.
2646+ *
2647+ * You should have received a copy of the GNU Lesser General Public License
2648+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2649+ */
2650+
2651+package au.edu.unimelb.csse.mugle.shared.api;
2652+
2653+import java.io.Serializable;
2654+
2655+/** Provides static (user-independent) information about a badge.
2656+ * This is the information that the developers have provided to describe a
2657+ * badge in the MUGLE control panel.
2658+ */
2659+public class Badge implements Serializable {
2660+ private static final long serialVersionUID = 4335025238357031611L;
2661+
2662+ private String name;
2663+ private String displayName;
2664+ private String description;
2665+ private int maxProgress;
2666+
2667+ public Badge()
2668+ {
2669+ this.name = "";
2670+ this.displayName = "";
2671+ this.description = "";
2672+ this.maxProgress = 0;
2673+ }
2674+
2675+ /** Construct a new Badge object. */
2676+ public Badge(String name, String displayName, String description,
2677+ int maxProgress)
2678+ {
2679+ this.name = name;
2680+ this.displayName = displayName;
2681+ this.description = description;
2682+ this.maxProgress = maxProgress;
2683+ }
2684+
2685+ /** The short name used to identify a badge. */
2686+ public String getName() {
2687+ return name;
2688+ }
2689+
2690+ /** The long "friendly" string which names the badge for users. */
2691+ public String getDisplayName() {
2692+ return displayName;
2693+ }
2694+
2695+ /** The even longer text which describes how to earn the badge.
2696+ * This should be in the form of an instruction, such as "rescue the
2697+ * princess."
2698+ */
2699+ public String getDescription() {
2700+ return description;
2701+ }
2702+
2703+ /** For progress badges, the total number of progress units required to
2704+ * earn the badge. For non-progress badges, 0.
2705+ */
2706+ public int getMaxProgress() {
2707+ return maxProgress;
2708+ }
2709+
2710+ @Override
2711+ public String toString() {
2712+ return "Badge [" +
2713+ this.name + ", " +
2714+ this.displayName + ", " +
2715+ this.description + ", " +
2716+ this.maxProgress + "]";
2717+ }
2718+}
2719
2720=== added file 'src/au/edu/unimelb/csse/mugle/shared/api/BadgeError.java'
2721--- src/au/edu/unimelb/csse/mugle/shared/api/BadgeError.java 1970-01-01 00:00:00 +0000
2722+++ src/au/edu/unimelb/csse/mugle/shared/api/BadgeError.java 2011-04-16 12:23:28 +0000
2723@@ -0,0 +1,34 @@
2724+/* Melbourne University Game-based Learning Environment
2725+ * Copyright (C) 2011 The University of Melbourne
2726+ *
2727+ * This program is free software: you can redistribute it and/or modify
2728+ * it under the terms of the GNU Lesser General Public License as published
2729+ * by the Free Software Foundation, either version 3 of the License, or
2730+ * (at your option) any later version.
2731+ *
2732+ * This program is distributed in the hope that it will be useful,
2733+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2734+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2735+ * GNU Lesser General Public License for more details.
2736+ *
2737+ * You should have received a copy of the GNU Lesser General Public License
2738+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2739+ */
2740+
2741+package au.edu.unimelb.csse.mugle.shared.api;
2742+
2743+/** An error relating to the badge service.
2744+ */
2745+public class BadgeError extends Exception {
2746+ private static final long serialVersionUID = -5517149280375900036L;
2747+
2748+ public BadgeError()
2749+ {
2750+ super();
2751+ }
2752+
2753+ public BadgeError(String message)
2754+ {
2755+ super(message);
2756+ }
2757+}
2758
2759=== added file 'src/au/edu/unimelb/csse/mugle/shared/api/GameTokenError.java'
2760--- src/au/edu/unimelb/csse/mugle/shared/api/GameTokenError.java 1970-01-01 00:00:00 +0000
2761+++ src/au/edu/unimelb/csse/mugle/shared/api/GameTokenError.java 2011-04-16 12:23:28 +0000
2762@@ -0,0 +1,34 @@
2763+/* Melbourne University Game-based Learning Environment
2764+ * Copyright (C) 2011 The University of Melbourne
2765+ *
2766+ * This program is free software: you can redistribute it and/or modify
2767+ * it under the terms of the GNU Lesser General Public License as published
2768+ * by the Free Software Foundation, either version 3 of the License, or
2769+ * (at your option) any later version.
2770+ *
2771+ * This program is distributed in the hope that it will be useful,
2772+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2773+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2774+ * GNU Lesser General Public License for more details.
2775+ *
2776+ * You should have received a copy of the GNU Lesser General Public License
2777+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2778+ */
2779+
2780+package au.edu.unimelb.csse.mugle.shared.api;
2781+
2782+/** An error passing a game token to one of the API methods.
2783+ */
2784+public class GameTokenError extends Exception {
2785+ private static final long serialVersionUID = 4167419343442742185L;
2786+
2787+ public GameTokenError()
2788+ {
2789+ super();
2790+ }
2791+
2792+ public GameTokenError(String gameToken)
2793+ {
2794+ super("A game with the gameToken: " + gameToken + " does not exist.");
2795+ }
2796+}
2797
2798=== added file 'src/au/edu/unimelb/csse/mugle/shared/api/KeyError.java'
2799--- src/au/edu/unimelb/csse/mugle/shared/api/KeyError.java 1970-01-01 00:00:00 +0000
2800+++ src/au/edu/unimelb/csse/mugle/shared/api/KeyError.java 2011-04-16 12:23:28 +0000
2801@@ -0,0 +1,43 @@
2802+/* Melbourne University Game-based Learning Environment
2803+ * Copyright (C) 2011 The University of Melbourne
2804+ *
2805+ * This program is free software: you can redistribute it and/or modify
2806+ * it under the terms of the GNU Lesser General Public License as published
2807+ * by the Free Software Foundation, either version 3 of the License, or
2808+ * (at your option) any later version.
2809+ *
2810+ * This program is distributed in the hope that it will be useful,
2811+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2812+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2813+ * GNU Lesser General Public License for more details.
2814+ *
2815+ * You should have received a copy of the GNU Lesser General Public License
2816+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2817+ */
2818+
2819+package au.edu.unimelb.csse.mugle.shared.api;
2820+
2821+/** An error for the key-value store; a key was not found.
2822+ */
2823+public class KeyError extends Exception {
2824+ private static final long serialVersionUID = 2248222166311987494L;
2825+
2826+ private String key;
2827+
2828+ public KeyError()
2829+ {
2830+ super();
2831+ this.key = null;
2832+ }
2833+
2834+ public KeyError(String key)
2835+ {
2836+ super("Key not found: " + key);
2837+ this.key = key;
2838+ }
2839+
2840+ public String getKey()
2841+ {
2842+ return this.key;
2843+ }
2844+}
2845
2846=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/Achievement.java'
2847--- src/au/edu/unimelb/csse/mugle/shared/model/Achievement.java 2011-04-08 10:13:04 +0000
2848+++ src/au/edu/unimelb/csse/mugle/shared/model/Achievement.java 2011-04-16 12:23:28 +0000
2849@@ -23,12 +23,17 @@
2850
2851 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
2852
2853-@SuppressWarnings("serial")
2854 @MugleDataWrapper
2855 public class Achievement extends ModelClass<Long, Achievement> {
2856
2857+ private static final long serialVersionUID = -578289425640382697L;
2858+
2859+ // Fields
2860+
2861 private String name;
2862
2863+ private String displayName;
2864+
2865 private String description;
2866
2867 private Game game;
2868@@ -43,14 +48,13 @@
2869 // Constructors
2870
2871 public Achievement() {
2872-
2873 this.userAchievementKeys = null;
2874 this.name = null;
2875+ this.setDisplayName(null);
2876 this.description = null;
2877 this.maxProgress = null;
2878 this.game = null;
2879- //TODO: Image
2880-
2881+ //TODO: Image
2882 }
2883
2884 // Getters
2885@@ -59,6 +63,10 @@
2886 return this.name;
2887 }
2888
2889+ public String getDisplayName() {
2890+ return displayName;
2891+ }
2892+
2893 public String getDescription() {
2894 return this.description;
2895 }
2896@@ -91,6 +99,10 @@
2897 this.name = newName;
2898 }
2899
2900+ public void setDisplayName(String displayName) {
2901+ this.displayName = displayName;
2902+ }
2903+
2904 public void setDescription(String newDescription) {
2905 this.description = newDescription;
2906 }
2907
2908=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/DevTeam.java'
2909--- src/au/edu/unimelb/csse/mugle/shared/model/DevTeam.java 2011-04-08 10:13:04 +0000
2910+++ src/au/edu/unimelb/csse/mugle/shared/model/DevTeam.java 2011-04-16 12:23:28 +0000
2911@@ -23,12 +23,12 @@
2912
2913 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
2914
2915-@SuppressWarnings("serial")
2916 @MugleDataWrapper
2917 public class DevTeam extends ModelClass<Long, DevTeam> {
2918
2919+ private static final long serialVersionUID = -8745604337821752467L;
2920
2921- // Fields
2922+ //Fields
2923
2924 private String urlName; //Must be unique
2925
2926
2927=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/Game.java'
2928--- src/au/edu/unimelb/csse/mugle/shared/model/Game.java 2011-04-08 10:13:04 +0000
2929+++ src/au/edu/unimelb/csse/mugle/shared/model/Game.java 2011-04-16 12:23:28 +0000
2930@@ -23,11 +23,13 @@
2931
2932 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
2933
2934-@SuppressWarnings("serial")
2935 @MugleDataWrapper
2936 public class Game extends ModelClass<Long, Game> {
2937
2938- /** The maximum possible game rating. */
2939+ private static final long serialVersionUID = -5139341163256410284L;
2940+
2941+
2942+ /** The maximum possible game rating. */
2943 public static final int MAX_RATING = 100;
2944
2945 // Fields
2946@@ -39,6 +41,8 @@
2947 private Integer totalRatings; // number of users who have rated this game
2948
2949 private DevTeam devTeam;
2950+
2951+ private String gameToken;
2952
2953 private Set<Long> achievementKeys;
2954
2955@@ -50,7 +54,7 @@
2956 // Constructors
2957
2958 public Game() {
2959-
2960+ this.gameToken = null;
2961 this.gameVersionKeys = null;
2962 this.ugpKeys = null;
2963 this.achievementKeys = null;
2964@@ -138,4 +142,12 @@
2965 this.ugpKeys = ugps;
2966 }
2967
2968+ public void setGameToken(String gameToken) {
2969+ this.gameToken = gameToken;
2970+ }
2971+
2972+ public String getGameToken() {
2973+ return gameToken;
2974+ }
2975+
2976 }
2977\ No newline at end of file
2978
2979=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/GameFile.java'
2980--- src/au/edu/unimelb/csse/mugle/shared/model/GameFile.java 2011-04-08 10:13:04 +0000
2981+++ src/au/edu/unimelb/csse/mugle/shared/model/GameFile.java 2011-04-16 12:23:28 +0000
2982@@ -24,19 +24,25 @@
2983 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
2984
2985 @MugleDataWrapper
2986-@SuppressWarnings("serial")
2987 public class GameFile extends ModelClass<String, GameFile> {
2988
2989-
2990- // Fields
2991-
2992+ private static final long serialVersionUID = -4361821523009813698L;
2993+
2994+ // Fields
2995+
2996 private String path; //path to the file relative to the Game URL
2997
2998+ private String mimeType; //mime type of the file
2999+
3000+ private String blobKey; //key to the actual blob
3001+
3002 private Set<Long> gameVersionKeys; //Game versions this file belongs to
3003
3004 // Constructors
3005 public GameFile() {
3006 this.gameVersionKeys = null;
3007+ this.mimeType = null;
3008+ this.blobKey = null;
3009 this.path = null;
3010 }
3011
3012@@ -68,5 +74,21 @@
3013 public void setGameVersionKeys(Set<Long> versions) {
3014 this.gameVersionKeys = versions;
3015 }
3016+
3017+ public void setMimeType(String mimeType) {
3018+ this.mimeType = mimeType;
3019+ }
3020+
3021+ public String getMimeType() {
3022+ return mimeType;
3023+ }
3024+
3025+ public void setBlobKey(String blobKey) {
3026+ this.blobKey = blobKey;
3027+ }
3028+
3029+ public String getBlobKey() {
3030+ return blobKey;
3031+ }
3032
3033 }
3034
3035=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/GameVersion.java'
3036--- src/au/edu/unimelb/csse/mugle/shared/model/GameVersion.java 2011-04-08 10:13:04 +0000
3037+++ src/au/edu/unimelb/csse/mugle/shared/model/GameVersion.java 2011-04-16 12:23:28 +0000
3038@@ -24,10 +24,11 @@
3039 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
3040
3041 @MugleDataWrapper
3042-@SuppressWarnings("serial")
3043 public class GameVersion extends ModelClass<Long, GameVersion> {
3044
3045
3046+ private static final long serialVersionUID = -3598516897405942476L;
3047+
3048 // Fields
3049
3050 /*
3051
3052=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/InvalidRatingException.java'
3053--- src/au/edu/unimelb/csse/mugle/shared/model/InvalidRatingException.java 2011-03-10 03:38:23 +0000
3054+++ src/au/edu/unimelb/csse/mugle/shared/model/InvalidRatingException.java 2011-04-16 12:23:28 +0000
3055@@ -17,8 +17,11 @@
3056
3057 package au.edu.unimelb.csse.mugle.shared.model;
3058
3059-@SuppressWarnings("serial")
3060+
3061 public class InvalidRatingException extends Exception {
3062+
3063+ private static final long serialVersionUID = 8363848579992882462L;
3064+
3065 public InvalidRatingException(int rating) {
3066 super("Rating " + rating + " is invalid. Rating must be between 0 and "
3067 + Game.MAX_RATING + ".");
3068
3069=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/KeyValuePair.java'
3070--- src/au/edu/unimelb/csse/mugle/shared/model/KeyValuePair.java 2011-03-30 15:46:59 +0000
3071+++ src/au/edu/unimelb/csse/mugle/shared/model/KeyValuePair.java 2011-04-16 12:23:28 +0000
3072@@ -19,12 +19,13 @@
3073
3074 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
3075
3076-@SuppressWarnings("serial")
3077 @MugleDataWrapper
3078 public class KeyValuePair extends ModelClass<Long, KeyValuePair> {
3079
3080
3081- // Fields
3082+ private static final long serialVersionUID = 2222512665326609908L;
3083+
3084+ // Fields
3085
3086 private UserGameProfile ugp;
3087
3088@@ -39,8 +40,7 @@
3089 this.ugp = null;
3090 this.value = null;
3091 }
3092-
3093-
3094+
3095 // Getters
3096
3097 public String getKey() {
3098
3099=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/PromotedGame.java'
3100--- src/au/edu/unimelb/csse/mugle/shared/model/PromotedGame.java 2011-03-30 15:46:59 +0000
3101+++ src/au/edu/unimelb/csse/mugle/shared/model/PromotedGame.java 2011-04-16 12:23:28 +0000
3102@@ -19,13 +19,13 @@
3103
3104 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
3105
3106-@SuppressWarnings("serial")
3107 @MugleDataWrapper
3108 public class PromotedGame extends ModelClass<String, PromotedGame> {
3109
3110+ private static final long serialVersionUID = -7822465832242079100L;
3111
3112 // Fields
3113-
3114+
3115 private String urlName;
3116
3117 private GameVersion gameVersion;
3118
3119=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/User.java'
3120--- src/au/edu/unimelb/csse/mugle/shared/model/User.java 2011-04-08 10:13:04 +0000
3121+++ src/au/edu/unimelb/csse/mugle/shared/model/User.java 2011-04-16 12:23:28 +0000
3122@@ -23,13 +23,15 @@
3123
3124 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
3125
3126-@SuppressWarnings("serial")
3127 @MugleDataWrapper
3128 public class User extends ModelClass<Long, User> {
3129
3130-
3131- // Fields
3132-
3133+ private static final long serialVersionUID = 3216382827435913653L;
3134+
3135+ //Fields
3136+
3137+ private String googleID; //Unique id provided by google
3138+
3139 private String urlName; //Must be unique
3140
3141 private String fullName;
3142@@ -48,7 +50,7 @@
3143 // Constructors
3144
3145 public User() {
3146-
3147+ this.googleID = null;
3148 this.devTeamKeys = null;
3149 this.ugpKeys = null;
3150 this.urlName = null;
3151@@ -102,6 +104,10 @@
3152 public Class<User> getClassType() {
3153 return User.class;
3154 }
3155+
3156+ public String getGoogleID() {
3157+ return googleID;
3158+ }
3159
3160 // Setters
3161
3162@@ -130,5 +136,9 @@
3163 public void setActive(Boolean active) {
3164 this.active = active;
3165 }
3166-
3167+
3168+ public void setGoogleID(String googleID) {
3169+ this.googleID = googleID;
3170+ }
3171+
3172 }
3173
3174=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/UserAchievement.java'
3175--- src/au/edu/unimelb/csse/mugle/shared/model/UserAchievement.java 2011-03-30 15:46:59 +0000
3176+++ src/au/edu/unimelb/csse/mugle/shared/model/UserAchievement.java 2011-04-16 12:23:28 +0000
3177@@ -19,12 +19,10 @@
3178
3179 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
3180
3181-@SuppressWarnings("serial")
3182 @MugleDataWrapper
3183 public class UserAchievement extends ModelClass<Long, UserAchievement> {
3184
3185-
3186- // Fields
3187+ private static final long serialVersionUID = 3314647480043897974L;
3188
3189 private UserGameProfile ugp;
3190
3191@@ -34,9 +32,6 @@
3192
3193 private Integer progress;
3194
3195- //By default assume a lack of this object means no progress towards achievement
3196-
3197-
3198 // Constructors
3199
3200 public UserAchievement() {
3201@@ -46,7 +41,6 @@
3202 this.progress = null;
3203 }
3204
3205-
3206 // Getters
3207
3208 public UserGameProfile getUserGameProfile() {
3209@@ -80,7 +74,7 @@
3210 this.achievement = achievement;
3211 }
3212
3213- public void setProgress(Integer progress) {
3214+ public void setProgress(Integer progress) {
3215 this.progress = progress;
3216 }
3217
3218
3219=== modified file 'src/au/edu/unimelb/csse/mugle/shared/model/UserGameProfile.java'
3220--- src/au/edu/unimelb/csse/mugle/shared/model/UserGameProfile.java 2011-04-08 10:13:04 +0000
3221+++ src/au/edu/unimelb/csse/mugle/shared/model/UserGameProfile.java 2011-04-16 12:23:28 +0000
3222@@ -23,12 +23,13 @@
3223
3224 import au.edu.unimelb.csse.mugle.shared.model.annotations.*;
3225
3226-@SuppressWarnings("serial")
3227 @MugleDataWrapper
3228 public class UserGameProfile extends ModelClass<Long, UserGameProfile> {
3229
3230-
3231- // Fields
3232+ private static final long serialVersionUID = 4735516690085498233L;
3233+
3234+ // Fields
3235+
3236 private Integer highscore;
3237
3238 private User user;
3239@@ -87,7 +88,6 @@
3240 return UserGameProfile.class;
3241 }
3242
3243-
3244 // Setters
3245
3246 public void setGame(Game game) {
3247@@ -101,7 +101,7 @@
3248 /* can only be set by the current Game */
3249 public void setHighscore(Integer newScore) {
3250 this.highscore = newScore;
3251- }
3252+ }
3253
3254 public void setKeyValuePairKeys(Set<Long> keyValuePair) {
3255 this.keyValuePairKeys = keyValuePair;
3256
3257=== added file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/AchievementNotExists.java'
3258--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/AchievementNotExists.java 1970-01-01 00:00:00 +0000
3259+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/AchievementNotExists.java 2011-04-16 12:23:28 +0000
3260@@ -0,0 +1,40 @@
3261+/* Melbourne University Game-based Learning Environment
3262+ * Copyright (C) 2011 The University of Melbourne
3263+ *
3264+ * This program is free software: you can redistribute it and/or modify
3265+ * it under the terms of the GNU General Public License as published by
3266+ * the Free Software Foundation, either version 3 of the License, or
3267+ * (at your option) any later version.
3268+ *
3269+ * This program is distributed in the hope that it will be useful,
3270+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3271+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3272+ * GNU General Public License for more details.
3273+ *
3274+ * You should have received a copy of the GNU General Public License
3275+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3276+ */
3277+
3278+package au.edu.unimelb.csse.mugle.shared.platform.exceptions;
3279+
3280+import java.io.Serializable;
3281+
3282+public class AchievementNotExists extends Exception implements Serializable {
3283+ /**
3284+ *
3285+ */
3286+ private static final long serialVersionUID = 1007635148933156162L;
3287+
3288+ public AchievementNotExists() {
3289+ super();
3290+ }
3291+
3292+ public AchievementNotExists(String gameName, String name) {
3293+ super("Achievement '" + name + "' does not exist for game '"
3294+ + gameName + "'");
3295+ }
3296+
3297+ public AchievementNotExists(Long primaryKey) {
3298+ super("Achievement with id '" + primaryKey + "' does not exist");
3299+ }
3300+}
3301
3302=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamExists.java'
3303--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamExists.java 2011-03-16 12:12:34 +0000
3304+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamExists.java 2011-04-16 12:23:28 +0000
3305@@ -24,9 +24,13 @@
3306 /**
3307 * Exception used when a new dev team is to be created but the team already exists.
3308 */
3309-@SuppressWarnings("serial")
3310 public class DevTeamExists extends Exception implements Serializable {
3311
3312+ /**
3313+ *
3314+ */
3315+ private static final long serialVersionUID = -1358761246676093332L;
3316+
3317 public DevTeamExists() {
3318 super();
3319 }
3320
3321=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamNotExists.java'
3322--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamNotExists.java 2011-03-16 12:12:34 +0000
3323+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/DevTeamNotExists.java 2011-04-16 12:23:28 +0000
3324@@ -24,9 +24,13 @@
3325 /**
3326 * Exception used when a given dev team does not exist.
3327 */
3328-@SuppressWarnings("serial")
3329 public class DevTeamNotExists extends Exception implements Serializable {
3330
3331+ /**
3332+ *
3333+ */
3334+ private static final long serialVersionUID = -4803672172249761591L;
3335+
3336 public DevTeamNotExists() {
3337 super();
3338 }
3339
3340=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameExists.java'
3341--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameExists.java 2011-03-16 12:12:34 +0000
3342+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameExists.java 2011-04-16 12:23:28 +0000
3343@@ -24,9 +24,13 @@
3344 /**
3345 * Exception used when a new game is to be created but the game already exists.
3346 */
3347-@SuppressWarnings("serial")
3348 public class GameExists extends Exception implements Serializable {
3349
3350+ /**
3351+ *
3352+ */
3353+ private static final long serialVersionUID = 77823808801952791L;
3354+
3355 public GameExists() {
3356 super();
3357 }
3358
3359=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameNotExists.java'
3360--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameNotExists.java 2011-03-16 12:12:34 +0000
3361+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameNotExists.java 2011-04-16 12:23:28 +0000
3362@@ -24,9 +24,13 @@
3363 /**
3364 * Exception used when a given game does not exists.
3365 */
3366-@SuppressWarnings("serial")
3367 public class GameNotExists extends Exception implements Serializable {
3368
3369+ /**
3370+ *
3371+ */
3372+ private static final long serialVersionUID = -921450195750245805L;
3373+
3374 public GameNotExists() {
3375 super();
3376 }
3377
3378=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionExists.java'
3379--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionExists.java 2011-03-20 11:06:48 +0000
3380+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionExists.java 2011-04-16 12:23:28 +0000
3381@@ -24,9 +24,13 @@
3382 /**
3383 * Exception used when a new game version is to be created but the game version already exists.
3384 */
3385-@SuppressWarnings("serial")
3386 public class GameVersionExists extends Exception implements Serializable {
3387
3388+ /**
3389+ *
3390+ */
3391+ private static final long serialVersionUID = -1838656621043022076L;
3392+
3393 public GameVersionExists() {
3394 super();
3395 }
3396
3397=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionNotExists.java'
3398--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionNotExists.java 2011-03-20 11:06:48 +0000
3399+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/GameVersionNotExists.java 2011-04-16 12:23:28 +0000
3400@@ -24,9 +24,13 @@
3401 /**
3402 * Exception used when a given game version does not exist.
3403 */
3404-@SuppressWarnings("serial")
3405 public class GameVersionNotExists extends Exception implements Serializable {
3406
3407+ /**
3408+ *
3409+ */
3410+ private static final long serialVersionUID = 8443470039286468097L;
3411+
3412 public GameVersionNotExists() {
3413 super();
3414 }
3415
3416=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameExists.java'
3417--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameExists.java 2011-03-16 12:12:34 +0000
3418+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameExists.java 2011-04-16 12:23:28 +0000
3419@@ -24,9 +24,13 @@
3420 /**
3421 * Exception used when a new promoted game is to be created but the promoted game already exists.
3422 */
3423-@SuppressWarnings("serial")
3424 public class PromotedGameExists extends Exception implements Serializable{
3425
3426+ /**
3427+ *
3428+ */
3429+ private static final long serialVersionUID = 8952108432578356503L;
3430+
3431 public PromotedGameExists() {
3432 super();
3433 }
3434
3435=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameNotExists.java'
3436--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameNotExists.java 2011-03-16 12:12:34 +0000
3437+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/PromotedGameNotExists.java 2011-04-16 12:23:28 +0000
3438@@ -24,9 +24,13 @@
3439 /**
3440 * Exception used when a given promoted game does not exist.
3441 */
3442-@SuppressWarnings("serial")
3443 public class PromotedGameNotExists extends Exception implements Serializable{
3444
3445+ /**
3446+ *
3447+ */
3448+ private static final long serialVersionUID = 491619454215655500L;
3449+
3450 public PromotedGameNotExists() {
3451 super();
3452 }
3453
3454=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserExists.java'
3455--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserExists.java 2011-03-16 12:12:34 +0000
3456+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserExists.java 2011-04-16 12:23:28 +0000
3457@@ -24,9 +24,13 @@
3458 /**
3459 * Exception used when a new user is to be created but the user already exists.
3460 */
3461-@SuppressWarnings("serial")
3462 public class UserExists extends Exception implements Serializable{
3463
3464+ /**
3465+ *
3466+ */
3467+ private static final long serialVersionUID = -6023406419592834887L;
3468+
3469 public UserExists() {
3470 super();
3471 }
3472
3473=== added file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserGameProfileNotExists.java'
3474--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserGameProfileNotExists.java 1970-01-01 00:00:00 +0000
3475+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserGameProfileNotExists.java 2011-04-16 12:23:28 +0000
3476@@ -0,0 +1,42 @@
3477+/* Melbourne University Game-based Learning Environment
3478+ * Copyright (C) 2011 The University of Melbourne
3479+ *
3480+ * This program is free software: you can redistribute it and/or modify
3481+ * it under the terms of the GNU General Public License as published by
3482+ * the Free Software Foundation, either version 3 of the License, or
3483+ * (at your option) any later version.
3484+ *
3485+ * This program is distributed in the hope that it will be useful,
3486+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3487+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3488+ * GNU General Public License for more details.
3489+ *
3490+ * You should have received a copy of the GNU General Public License
3491+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3492+ */
3493+
3494+package au.edu.unimelb.csse.mugle.shared.platform.exceptions;
3495+
3496+import java.io.Serializable;
3497+
3498+import au.edu.unimelb.csse.mugle.shared.model.Game;
3499+import au.edu.unimelb.csse.mugle.shared.model.User;
3500+
3501+public class UserGameProfileNotExists extends Exception implements Serializable {
3502+ /**
3503+ *
3504+ */
3505+ private static final long serialVersionUID = -6486386063392954899L;
3506+
3507+ public UserGameProfileNotExists() {
3508+ super();
3509+ }
3510+
3511+ public UserGameProfileNotExists(User u, Game g) {
3512+ super("A UserGameProfile for the User " + u.getUrlName() + " for the game " + g.getUrlName() + " does not exist");
3513+ }
3514+
3515+ public UserGameProfileNotExists(Long primaryKey) {
3516+ super("A UserGameProfile with the primary key: " + primaryKey + " does not exist.");
3517+ }
3518+}
3519
3520=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserNotExists.java'
3521--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserNotExists.java 2011-03-16 12:12:34 +0000
3522+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserNotExists.java 2011-04-16 12:23:28 +0000
3523@@ -24,9 +24,13 @@
3524 /**
3525 * Exception used when a given user does not exist.
3526 */
3527-@SuppressWarnings("serial")
3528 public class UserNotExists extends Exception implements Serializable{
3529
3530+ /**
3531+ *
3532+ */
3533+ private static final long serialVersionUID = -209272321411054068L;
3534+
3535 public UserNotExists() {
3536 super();
3537 }
3538@@ -36,7 +40,7 @@
3539 }
3540
3541 public UserNotExists(String urlName) {
3542- super("User + '" + urlName + "' does not exist");
3543+ super("User '" + urlName + "' does not exist");
3544 }
3545
3546 public UserNotExists(Long id) {
3547
3548=== modified file 'src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserPrivilegeException.java'
3549--- src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserPrivilegeException.java 2011-03-16 12:12:34 +0000
3550+++ src/au/edu/unimelb/csse/mugle/shared/platform/exceptions/UserPrivilegeException.java 2011-04-16 12:23:28 +0000
3551@@ -23,10 +23,14 @@
3552 import au.edu.unimelb.csse.mugle.shared.model.User;
3553 import au.edu.unimelb.csse.mugle.shared.model.Role;
3554
3555-@SuppressWarnings("serial")
3556 public class UserPrivilegeException extends Exception implements Serializable {
3557
3558 /**
3559+ *
3560+ */
3561+ private static final long serialVersionUID = 6418600873641304072L;
3562+
3563+ /**
3564 *
3565 * @param u The user that's trying the operation
3566 * @param r The required role
3567
3568=== modified file 'war/WEB-INF/web.xml'
3569--- war/WEB-INF/web.xml 2011-04-08 09:52:55 +0000
3570+++ war/WEB-INF/web.xml 2011-04-16 12:23:28 +0000
3571@@ -4,7 +4,6 @@
3572 "http://java.sun.com/dtd/web-app_2_3.dtd">
3573
3574 <web-app>
3575-
3576 <!-- Default page to serve -->
3577 <welcome-file-list>
3578 <welcome-file>Mugle.html</welcome-file>
3579@@ -62,7 +61,7 @@
3580 <url-pattern>/mugle/users</url-pattern>
3581 </servlet-mapping>
3582
3583- <servlet>
3584+ <servlet>
3585 <servlet-name>DataService</servlet-name>
3586 <servlet-class>au.edu.unimelb.csse.mugle.server.model.DataServiceImpl</servlet-class>
3587 </servlet>
3588@@ -81,5 +80,47 @@
3589 <servlet-name>FileIOService</servlet-name>
3590 <url-pattern>/mugle/files</url-pattern>
3591 </servlet-mapping>
3592+
3593+ <!-- API servlet mappings -->
3594+
3595+ <servlet>
3596+ <servlet-name>keyValueServlet</servlet-name>
3597+ <servlet-class>au.edu.unimelb.csse.mugle.server.api.KeyValueServiceImpl</servlet-class>
3598+ </servlet>
3599+
3600+ <servlet-mapping>
3601+ <servlet-name>keyValueServlet</servlet-name>
3602+ <url-pattern>/mugle/api-keyvalue</url-pattern>
3603+ </servlet-mapping>
3604+
3605+ <servlet>
3606+ <servlet-name>UserServlet</servlet-name>
3607+ <servlet-class>au.edu.unimelb.csse.mugle.server.api.UserServiceImpl</servlet-class>
3608+ </servlet>
3609+
3610+ <servlet-mapping>
3611+ <servlet-name>UserServlet</servlet-name>
3612+ <url-pattern>/mugle/api-user</url-pattern>
3613+ </servlet-mapping>
3614+
3615+ <servlet>
3616+ <servlet-name>HighscoreServlet</servlet-name>
3617+ <servlet-class>au.edu.unimelb.csse.mugle.server.api.HighscoreServiceImpl</servlet-class>
3618+ </servlet>
3619+
3620+ <servlet-mapping>
3621+ <servlet-name>HighscoreServlet</servlet-name>
3622+ <url-pattern>/mugle/api-highscore</url-pattern>
3623+ </servlet-mapping>
3624+
3625+ <servlet>
3626+ <servlet-name>BadgeServlet</servlet-name>
3627+ <servlet-class>au.edu.unimelb.csse.mugle.server.api.BadgeServiceImpl</servlet-class>
3628+ </servlet>
3629+
3630+ <servlet-mapping>
3631+ <servlet-name>BadgeServlet</servlet-name>
3632+ <url-pattern>/mugle/api-badge</url-pattern>
3633+ </servlet-mapping>
3634
3635 </web-app>

Subscribers

People subscribed via source and target branches