Author: lryan
Date: Mon Jul 7 17:22:19 2008
New Revision: 674686
URL: http://svn.apache.org/viewvc?rev=674686&view=rev
Log:
Dataservice implementation backed by the canonical JSON file.
Added:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/canonical/JSONOpensocialService.java
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/canonical/JSONOpensocialServiceTest.java
Modified:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/model/Person.java
incubator/shindig/trunk/javascript/sampledata/canonicaldb.json
Added:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/canonical/JSONOpensocialService.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/canonical/JSONOpensocialService.java?rev=674686&view=auto
==============================================================================
---
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/canonical/JSONOpensocialService.java
(added)
+++
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/canonical/JSONOpensocialService.java
Mon Jul 7 17:22:19 2008
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shindig.social.canonical;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.shindig.common.SecurityToken;
+import org.apache.shindig.social.ResponseError;
+import org.apache.shindig.social.ResponseItem;
+import org.apache.shindig.social.dataservice.ActivityService;
+import org.apache.shindig.social.dataservice.AppDataService;
+import org.apache.shindig.social.dataservice.DataCollection;
+import org.apache.shindig.social.dataservice.GroupId;
+import org.apache.shindig.social.dataservice.PersonService;
+import org.apache.shindig.social.dataservice.RestfulCollection;
+import org.apache.shindig.social.dataservice.UserId;
+import org.apache.shindig.social.opensocial.model.Activity;
+import org.apache.shindig.social.opensocial.model.Person;
+import org.apache.shindig.social.opensocial.util.BeanConverter;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation of supported services backed by a JSON DB
+ */
+public class JSONOpensocialService implements ActivityService, PersonService,
AppDataService {
+
+ /**
+ * The DB
+ */
+ private JSONObject db;
+
+ /**
+ * The JSON<->Bean converter
+ */
+ private BeanConverter converter;
+
+ /**
+ * db["activities"] -> Array<Person>
+ */
+ private static final String PEOPLE_TABLE = "people";
+
+ /**
+ * db["people"] -> Map<Person.Id, Array<Activity>>
+ */
+ private static final String ACTIVITIES_TABLE = "activities";
+
+ /**
+ * db["data"] -> Map<Person.Id, Map<String, String>>
+ */
+ private static final String DATA_TABLE = "data";
+
+ /**
+ * db["friendLinks"] -> Map<Person.Id, Array<Person.Id>>
+ */
+ private static final String FRIEND_LINK_TABLE = "friendLinks";
+
+ @Inject
+ public JSONOpensocialService(@Named("canonical.json.db")String jsonLocation,
+ BeanConverter converter) throws Exception {
+ String content = IOUtils.toString(new
java.net.URL(jsonLocation).openStream(), "UTF-8");
+ this.db = new JSONObject(content);
+ this.converter = converter;
+ }
+
+ public ResponseItem<RestfulCollection<Activity>> getActivities(UserId
userId, GroupId groupId,
+ String appId, Set<String> fields, SecurityToken token) {
+ List<Activity> result = Lists.newArrayList();
+ try {
+ // TODO Is it really valid to read activities across multiple users in
one rpc?
+ Set<String> idSet = getIdSet(userId, groupId, token);
+ for (String id : idSet) {
+ if (db.getJSONObject(ACTIVITIES_TABLE).has(id)) {
+ JSONArray activities =
db.getJSONObject(ACTIVITIES_TABLE).getJSONArray(id);
+ for (int i = 0; i < activities.length(); i++) {
+ JSONObject activity = activities.getJSONObject(i);
+ if (appId != null &&
activity.get(Activity.Field.APP_ID.toString()).equals(appId)) {
+ result.add(convertToActivity(activity, fields));
+ }
+ }
+ }
+ }
+ return new ResponseItem<RestfulCollection<Activity>>(new
RestfulCollection<Activity>(result));
+ } catch (JSONException je) {
+ return new
ResponseItem<RestfulCollection<Activity>>(ResponseError.INTERNAL_ERROR,
+ je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem<Activity> getActivity(UserId userId, GroupId groupId,
String appId,
+ Set<String> fields, String activityId, SecurityToken token) {
+ try {
+ if (db.getJSONObject(ACTIVITIES_TABLE).has(userId.getUserId(token))) {
+ JSONArray activities =
db.getJSONObject(ACTIVITIES_TABLE).getJSONArray(userId.getUserId(token));
+ for (int i = 0; i < activities.length(); i++) {
+ JSONObject activity = activities.getJSONObject(i);
+ if (userId != null && activity.get(Activity.Field.USER_ID.toString())
+ .equals(userId.getUserId(token)) &&
+ activity.get(Activity.Field.ID.toString()).equals(activityId)) {
+ return new ResponseItem<Activity>(convertToActivity(activity,
fields));
+ }
+ }
+ }
+ return null;
+ } catch (JSONException je) {
+ return new ResponseItem<Activity>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem deleteActivity(UserId userId, GroupId groupId, String
appId,
+ String activityId, SecurityToken token) {
+ try {
+ if (db.getJSONObject(ACTIVITIES_TABLE).has(userId.getUserId(token))) {
+ JSONArray activities =
db.getJSONObject(ACTIVITIES_TABLE).getJSONArray(userId.getUserId(token));
+ if (activities != null) {
+ JSONArray newList = new JSONArray();
+ for (int i = 0; i < activities.length(); i++) {
+ JSONObject activity = activities.getJSONObject(i);
+ if
(!activity.get(Activity.Field.ID.toString()).equals(activityId)) {
+ newList.put(activity);
+ }
+ }
+ db.getJSONObject(ACTIVITIES_TABLE).put(userId.getUserId(token),
newList);
+ // TODO. This seems very odd that we return no useful response in
this case
+ // There is no way to represent not-found
+ // if (found) { ??
+ //}
+ }
+ }
+ // What is the appropriate response here??
+ return new ResponseItem<Object>(null);
+ } catch (JSONException je) {
+ return new ResponseItem<Object>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem createActivity(UserId userId, GroupId groupId, String
appId,
+ Set<String> fields, Activity activity, SecurityToken token) {
+ // Are fields really needed here?
+ try {
+ JSONObject jsonObject = convertFromActivity(activity, fields);
+ if (!jsonObject.has(Activity.Field.ID.toString())) {
+ jsonObject.put(Activity.Field.ID.toString(),
System.currentTimeMillis());
+ }
+ JSONArray jsonArray =
db.getJSONObject(ACTIVITIES_TABLE).getJSONArray(userId.getUserId(token));
+ if (jsonArray == null) {
+ jsonArray = new JSONArray();
+ db.getJSONObject(ACTIVITIES_TABLE).put(userId.getUserId(token),
jsonArray);
+ }
+ jsonArray.put(jsonObject);
+ // TODO ??
+ return null;
+ } catch (JSONException je) {
+ return new ResponseItem<Object>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem<RestfulCollection<Person>> getPeople(UserId userId,
GroupId groupId,
+ SortOrder sortOrder, FilterType filter, int first, int max,
+ Set<String> fields, SecurityToken token) {
+ List<Person> result = Lists.newArrayList();
+ try {
+ JSONArray people = db.getJSONArray(PEOPLE_TABLE);
+
+ Set<String> idSet = getIdSet(userId, groupId, token);
+
+ for (int i = 0; i < people.length(); i++) {
+ JSONObject person = people.getJSONObject(i);
+ if (!idSet.contains(person.get(Person.Field.ID.toString()))) {
+ continue;
+ }
+ // Add group support later
+ result.add(convertToPerson(person, fields));
+ }
+ return new ResponseItem<RestfulCollection<Person>>(new
RestfulCollection<Person>(result));
+ } catch (JSONException je) {
+ return new
ResponseItem<RestfulCollection<Person>>(ResponseError.INTERNAL_ERROR,
+ je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem<Person> getPerson(UserId id, Set<String> fields,
SecurityToken token) {
+ try {
+ JSONArray people = db.getJSONArray(PEOPLE_TABLE);
+
+ for (int i = 0; i < people.length(); i++) {
+ JSONObject person = people.getJSONObject(i);
+ if (id != null && person.get(Person.Field.ID.toString())
+ .equals(id.getUserId(token))) {
+ return new ResponseItem<Person>(convertToPerson(person, fields));
+ }
+ }
+ // TODO What does this mean?
+ return null;
+ } catch (JSONException je) {
+ return new ResponseItem<Person>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem<DataCollection> getPersonData(UserId userId, GroupId
groupId, String appId,
+ Set<String> fields, SecurityToken token) {
+ // TODO. Does fields==null imply all?
+ try {
+ Map<String, Map<String, String>> idToData = Maps.newHashMap();
+ Set<String> idSet = getIdSet(userId, groupId, token);
+ for (String id : idSet) {
+ JSONObject personData;
+ if (!db.getJSONObject(DATA_TABLE).has(id)) {
+ personData = new JSONObject();
+ } else {
+ if (fields != null) {
+ personData = new JSONObject(
+ db.getJSONObject(DATA_TABLE).getJSONObject(id),
+ fields.toArray(new String[fields.size()]));
+ } else {
+ personData = db.getJSONObject(DATA_TABLE).getJSONObject(id);
+ }
+ }
+
+ Iterator keys = personData.keys();
+ Map<String, String> data = Maps.newHashMap();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ data.put(key, personData.getString(key));
+ }
+ idToData.put(id, data);
+ }
+ return new ResponseItem<DataCollection>(new DataCollection(idToData));
+ } catch (JSONException je) {
+ return new ResponseItem<DataCollection>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem deletePersonData(UserId userId, GroupId groupId, String
appId,
+ Set<String> fields, SecurityToken token) {
+ try {
+ if (!db.getJSONObject(DATA_TABLE).has(userId.getUserId(token))) {
+ return null;
+ }
+ JSONObject newPersonData = new JSONObject();
+ JSONObject oldPersonData =
db.getJSONObject(DATA_TABLE).getJSONObject(userId.getUserId(token));
+ Iterator keys = oldPersonData.keys();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ if (fields != null && !fields.contains(key)) {
+ newPersonData.put(key, oldPersonData.getString(key));
+ }
+ }
+ db.getJSONObject(DATA_TABLE).put(userId.getUserId(token), newPersonData);
+ // TODO what is the appropriate return value
+ return null;
+ } catch (JSONException je) {
+ return new ResponseItem<Object>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ public ResponseItem updatePersonData(UserId userId, GroupId groupId, String
appId,
+ Set<String> fields, Map<String, String> values, SecurityToken token) {
+ // TODO this seems redundant. No need to pass both fields and a map of
field->value
+ try {
+ JSONObject personData =
db.getJSONObject(DATA_TABLE).getJSONObject(userId.getUserId(token));
+ if (personData == null) {
+ personData = new JSONObject();
+ db.getJSONObject(DATA_TABLE).put(userId.getUserId(token), personData);
+ }
+
+ for (Map.Entry<String, String> entry : values.entrySet()) {
+ personData.put(entry.getKey(), entry.getValue());
+ }
+ // TODO what is the appropriate return value
+ return null;
+ } catch (JSONException je) {
+ return new ResponseItem<Object>(ResponseError.INTERNAL_ERROR,
je.getMessage(), null);
+ }
+ }
+
+ /**
+ * Get the set of user id's from a user and group
+ */
+ private Set<String> getIdSet(UserId user, GroupId group, SecurityToken token)
+ throws JSONException {
+ String userId = user.getUserId(token);
+
+ if (group == null) {
+ return Sets.newLinkedHashSet(userId);
+ }
+
+ Set<String> returnVal = Sets.newLinkedHashSet();
+ switch (group.getType()) {
+ case all:
+ case friends:
+ case groupId:
+ if (db.getJSONObject(FRIEND_LINK_TABLE).has(userId)) {
+ JSONArray friends =
db.getJSONObject(FRIEND_LINK_TABLE).getJSONArray(userId);
+ for (int i = 0; i < friends.length(); i++) {
+ returnVal.add(friends.getString(i));
+ }
+ }
+ break;
+ case self:
+ returnVal.add(userId);
+ break;
+ }
+ return returnVal;
+ }
+
+ private Activity convertToActivity(JSONObject object, Set<String> fields)
throws JSONException {
+ if (fields != null && !fields.isEmpty()) {
+ // Create a copy with just the specified fields
+ object = new JSONObject(object, fields.toArray(new
String[fields.size()]));
+ }
+ return converter.convertToObject(object.toString(), Activity.class);
+ }
+
+ private JSONObject convertFromActivity(Activity activity, Set<String> fields)
+ throws JSONException {
+ // TODO Not using fields yet
+ return new JSONObject(converter.convertToString(activity));
+ }
+
+ private Person convertToPerson(JSONObject object, Set<String> fields) throws
JSONException {
+ if (fields != null && !fields.isEmpty()) {
+ // Create a copy with just the specified fields
+ object = new JSONObject(object, fields.toArray(new
String[fields.size()]));
+ }
+ return converter.convertToObject(object.toString(), Person.class);
+ }
+}
Modified:
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/model/Person.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/model/Person.java?rev=674686&r1=674685&r2=674686&view=diff
==============================================================================
---
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/model/Person.java
(original)
+++
incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/model/Person.java
Mon Jul 7 17:22:19 2008
@@ -17,8 +17,11 @@
*/
package org.apache.shindig.social.opensocial.model;
-import java.util.List;
+import org.apache.shindig.social.opensocial.util.EnumUtil;
+
import java.util.Date;
+import java.util.List;
+import java.util.Set;
/**
* see
@@ -87,6 +90,12 @@
private final String jsonString;
+ public static final Set<String> DEFAULT_FIELDS =
+ EnumUtil.getEnumStrings(ID, NAME, THUMBNAIL_URL);
+
+ public static final Set<String> ALL_FIELDS =
+ EnumUtil.getEnumStrings(Field.values());
+
private Field(String jsonString) {
this.jsonString = jsonString;
}
Added:
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/canonical/JSONOpensocialServiceTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/canonical/JSONOpensocialServiceTest.java?rev=674686&view=auto
==============================================================================
---
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/canonical/JSONOpensocialServiceTest.java
(added)
+++
incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/canonical/JSONOpensocialServiceTest.java
Mon Jul 7 17:22:19 2008
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shindig.social.canonical;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.Guice;
+
+import junit.framework.TestCase;
+
+import org.apache.shindig.common.SecurityToken;
+import org.apache.shindig.common.testing.FakeGadgetToken;
+import org.apache.shindig.social.ResponseItem;
+import org.apache.shindig.social.SocialApiTestsGuiceModule;
+import org.apache.shindig.social.dataservice.DataCollection;
+import org.apache.shindig.social.dataservice.GroupId;
+import org.apache.shindig.social.dataservice.PersonService;
+import org.apache.shindig.social.dataservice.RestfulCollection;
+import org.apache.shindig.social.dataservice.UserId;
+import org.apache.shindig.social.opensocial.model.Activity;
+import org.apache.shindig.social.opensocial.model.Person;
+import org.apache.shindig.social.opensocial.util.BeanJsonConverter;
+
+/**
+ * Test the JSONOpensocialService
+ */
+public class JSONOpensocialServiceTest extends TestCase {
+
+ private JSONOpensocialService db;
+
+ private static final UserId CANON_USER = new UserId(UserId.Type.userId,
"canonical");
+ private static final GroupId SELF_GROUP = new GroupId(GroupId.Type.self,
null);
+ private static final String APP_ID = "1";
+
+ private static final String CANONICAL_USER_ID = "canonical";
+ private SecurityToken token = new FakeGadgetToken();
+
+
+ @Override
+ protected void setUp() throws Exception {
+ BeanJsonConverter beanJsonConverter = new BeanJsonConverter(
+ Guice.createInjector(new SocialApiTestsGuiceModule()));
+ db = new JSONOpensocialService(
+
"file:///home/lryan/shindig/trunk/javascript/sampledata/canonicaldb.json",
+ beanJsonConverter);
+ }
+
+ public void testGetPersonDefaultFields() throws Exception {
+ ResponseItem<Person> personResponseItem = db
+ .getPerson(CANON_USER, Person.Field.DEFAULT_FIELDS, token);
+
+ assertNotNull("Canonical user not found",
personResponseItem.getResponse());
+ assertNotNull("Canonical user has no id",
personResponseItem.getResponse().getId());
+ assertNotNull("Canonical user has no name",
personResponseItem.getResponse().getName());
+ assertNotNull("Canonical user has no thumbnail",
+ personResponseItem.getResponse().getThumbnailUrl());
+ }
+
+ public void testGetPersonAllFields() throws Exception {
+ ResponseItem<Person> personResponseItem = db
+ .getPerson(CANON_USER, Person.Field.ALL_FIELDS, token);
+ assertNotNull("Canonical user not found",
personResponseItem.getResponse());
+ }
+
+ public void testGetExpectedFriends() throws Exception {
+ ResponseItem<RestfulCollection<Person>> responseItem = db.getPeople(
+ CANON_USER, new GroupId(GroupId.Type.friends, null),
PersonService.SortOrder.topFriends,
+ PersonService.FilterType.all, 0, Integer.MAX_VALUE, null, token);
+ assertNotNull(responseItem.getResponse());
+ assertEquals(responseItem.getResponse().getTotalResults(), 4);
+ // Test a couple of users
+ assertEquals(responseItem.getResponse().getEntry().get(0).getId(),
"john.doe");
+ assertEquals(responseItem.getResponse().getEntry().get(1).getId(),
"jane.doe");
+ }
+
+ public void testGetExpectedActivities() throws Exception {
+ ResponseItem<RestfulCollection<Activity>> responseItem = db.getActivities(
+ CANON_USER, SELF_GROUP, APP_ID, null, new FakeGadgetToken());
+ assertTrue(responseItem.getResponse().getTotalResults() == 2);
+ }
+
+ public void testGetExpectedActivity() throws Exception {
+ ResponseItem<Activity> responseItem = db.getActivity(
+ CANON_USER, SELF_GROUP, APP_ID,
+ Sets.newHashSet("appId", "body", "mediaItems"), APP_ID, new
FakeGadgetToken());
+ assertTrue(responseItem != null);
+ assertTrue(responseItem.getResponse() != null);
+ // Check that some fields are fetched and others are not
+ assertTrue(responseItem.getResponse().getBody() != null);
+ assertTrue(responseItem.getResponse().getBodyId() == null);
+ }
+
+ public void testDeleteExpectedActivity() throws Exception {
+ db.deleteActivity(CANON_USER, SELF_GROUP, APP_ID, APP_ID,
+ new FakeGadgetToken());
+
+ // Try to fetch the activity
+ ResponseItem<Activity> responseItem = db.getActivity(
+ CANON_USER, SELF_GROUP, APP_ID,
+ Sets.newHashSet("appId", "body", "mediaItems"), APP_ID, new
FakeGadgetToken());
+ assertTrue(responseItem == null);
+ }
+
+ public void testGetExpectedAppData() throws Exception {
+ ResponseItem<DataCollection> responseItem = db.getPersonData(
+ CANON_USER, SELF_GROUP, APP_ID, null, new FakeGadgetToken());
+ assertTrue(!responseItem.getResponse().getEntry().isEmpty());
+
assertTrue(!responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).isEmpty());
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).size()
== 2);
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).containsKey("count"));
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).containsKey("size"));
+ }
+
+ public void testDeleteExpectedAppData() throws Exception {
+ // Delete the data
+ db.deletePersonData(CANON_USER, SELF_GROUP, APP_ID,
+ Sets.newHashSet("count"), new FakeGadgetToken());
+
+ //Fetch the remaining and test
+ ResponseItem<DataCollection> responseItem = db.getPersonData(
+ CANON_USER, SELF_GROUP, APP_ID, null, new FakeGadgetToken());
+ assertTrue(!responseItem.getResponse().getEntry().isEmpty());
+
assertTrue(!responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).isEmpty());
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).size()
== 1);
+
assertTrue(!responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).containsKey("count"));
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).containsKey("size"));
+ }
+
+ public void testUpdateExpectedAppData() throws Exception {
+ // Delete the data
+ db.updatePersonData(CANON_USER, SELF_GROUP, APP_ID,
+ null, Maps.immutableMap("count", "10", "newvalue", "20"), new
FakeGadgetToken());
+
+ //Fetch the remaining and test
+ ResponseItem<DataCollection> responseItem = db.getPersonData(
+ CANON_USER, SELF_GROUP, APP_ID, null, new FakeGadgetToken());
+ assertTrue(!responseItem.getResponse().getEntry().isEmpty());
+
assertTrue(!responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).isEmpty());
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).size()
== 3);
+
assertTrue(responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).containsKey("count"));
+ assertTrue(
+
responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).get("count").equals("10"));
+ assertTrue(
+
responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).containsKey("newvalue"));
+ assertTrue(
+
responseItem.getResponse().getEntry().get(CANONICAL_USER_ID).get("newvalue").equals("20"));
+ }
+}
Modified: incubator/shindig/trunk/javascript/sampledata/canonicaldb.json
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/javascript/sampledata/canonicaldb.json?rev=674686&r1=674685&r2=674686&view=diff
==============================================================================
--- incubator/shindig/trunk/javascript/sampledata/canonicaldb.json (original)
+++ incubator/shindig/trunk/javascript/sampledata/canonicaldb.json Mon Jul 7
17:22:19 2008
@@ -10,8 +10,8 @@
//
// Notes:
// - The structure of Person, Activity MUST! match those in the RESTful spec
-// - Data for "canonical" user should exercise every field in the spec. And
is relied on for unit-testing
-// so change at your peril
+// - Data for "canonical" user should exercise every field in the spec. And
is relied on
+// for unit-testing so change at your peril
// - Consider adding a structure for Map<Person.Id, Array<appId>> to
represent installed gadgets
//
// TODO:
@@ -175,7 +175,10 @@
},
{
"id" : "john.doe",
- "gender" : "M",
+ "gender" : {
+ "key" : "MALE",
+ "displayvalue" : "Male"
+ },
"hasApp" : true,
"name" : {
"familyName" : "Doe",
@@ -185,7 +188,10 @@
},
{
"id" : "jane.doe",
- "gender" : "F",
+ "gender" : {
+ "key" : "FEMALE",
+ "displayvalue" : "Female"
+ },
"hasApp" : true,
"name" : {
"familyName" : "Doe",
@@ -195,7 +201,10 @@
},
{
"id" : "george.doe",
- "gender" : "M",
+ "gender" : {
+ "key" : "MALE",
+ "displayvalue" : "Female"
+ },
"hasApp" : true,
"name" : {
"familyName" : "Doe",
@@ -205,7 +214,10 @@
},
{
"id" : "mario.rossi",
- "gender" : "M",
+ "gender" : {
+ "key" : "MALE",
+ "displayvalue" : "Male"
+ },
"hasApp" : true,
"name" : {
"familyName" : "Rossi",
@@ -215,7 +227,10 @@
},
{
"id" : "maija.m",
- "gender" : "F",
+ "gender" : {
+ "key" : "FEMALE",
+ "displayvalue" : "Female"
+ },
"hasApp" : true,
"name" : {
"familyName" : "Meikäläinen",
@@ -324,6 +339,7 @@
// ----------------------------- Data ---------------------------------------
//
"friendLinks" : {
+ "canonical" : ["john.doe", "jane.doe", "george.doe", "maija.m"],
"john.doe" : ["jane.doe", "george.doe", "maija.m"],
"jane.doe" : ["john.doe"],
"george.doe" : ["john.doe"],