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"],


Reply via email to