public static void setUpClass()
        {
            pc = new ParaClient("app:para", "ynJInh32zam7MzjBwBqwIVYtvm+tnsbBP1cpcq7PWmFhAmPsdua7HQ==");
            pc.setEndpoint("http://localhost:8080");
            pc2 = new ParaClient("app:para", null);
            pc2.setEndpoint("http://localhost:8080");
            if (pc.me() == null) {
                throw new Exception("Local Para server must be started before testing.");
            }

            u = new ParaObject("111");
            u.name = "John Doe";
            u.tags = new List<string> { "one", "two", "three" };

            u1 = new ParaObject("222");
            u1.name = "Joe Black";
            u1.tags = new List<string> { "two", "four", "three" };

            u2 = new ParaObject("333");
            u2.name = "Ann Smith";
            u2.tags = new List<string> { "four", "five", "three" };

            t = new ParaObject("tag:test", "tag");
            t["count"] = 3;
            t["tag"] = "test";

            a1 = new ParaObject("adr1", "address");
            a1.name = "Place 1";
            a1["address"] = "NYC";
            a1["country"] = "US";
            a1["latlng"] = "40.67,-73.94";
            a1.parentid = u.id;
            a1.creatorid = u.id;

            a2 = new ParaObject("adr2", "address");
            a2.name = "Place 2";
            a2["address"] = "NYC";
            a2["country"] = "US";
            a2["latlng"] = "40.69,-73.95";
            a2.parentid = t.id;
            a2.creatorid = t.id;

            s1 = new ParaObject("s1");
            s1.name = "This is a little test sentence. Testing, one, two, three.";

            s2 = new ParaObject("s2");
            s2.name = "We are testing this thing. This sentence is a test. One, two.";

            pc.createAll(new List<ParaObject> { u, u1, u2, t, s1, s2, a1, a2 });
            Thread.Sleep(1000);
        }
        public void testBatchCRUD()
        {
            List<ParaObject> dogs = new List<ParaObject>();
            for (int i = 0; i < 3; i++)
            {
                ParaObject s = new ParaObject();
                s.type = dogsType;
                s["foo"] = "bark!";
                dogs.Add(s);
            }

            Assert.IsTrue(pc.createAll(null).Count == 0);
            List<ParaObject> l1 = pc.createAll(dogs);
            Assert.AreEqual(3, l1.Count);
            Assert.IsNotNull(l1[0].id);

            Assert.IsTrue(pc.readAll(null).Count == 0);
            List<string> nl = new List<string>(3);
            Assert.IsTrue(pc.readAll(nl).Count == 0);
            nl.Add(l1[0].id);
            nl.Add(l1[1].id);
            nl.Add(l1[2].id);
            List<ParaObject> l2 = pc.readAll(nl);
            Assert.AreEqual(3, l2.Count);
            Assert.AreEqual(l1[0].id, l2[0].id);
            Assert.AreEqual(l1[1].id, l2[1].id);
            Assert.IsNotNull(l2[0]["foo"]);
            Assert.AreEqual("bark!", l2[0]["foo"]);

            Assert.IsTrue(pc.updateAll(null).Count == 0);

            ParaObject part1 = new ParaObject(l1[0].id);
            ParaObject part2 = new ParaObject(l1[1].id);
            ParaObject part3 = new ParaObject(l1[2].id);
            part1.type = dogsType;
            part2.type = dogsType;
            part3.type = dogsType;

            part1["custom"] = "prop";
            part1.name = "NewName1";
            part2.name = "NewName2";
            part3.name = "NewName3";

            List<ParaObject> l3 = pc.updateAll(new List<ParaObject> { part1, part2, part3 });

            Assert.IsNotNull(l3[0]["custom"]);
            Assert.AreEqual(dogsType, l3[0].type);
            Assert.AreEqual(dogsType, l3[1].type);
            Assert.AreEqual(dogsType, l3[2].type);

            Assert.AreEqual(part1.name, l3[0].name);
            Assert.AreEqual(part2.name, l3[1].name);
            Assert.AreEqual(part3.name, l3[2].name);

            pc.deleteAll(nl);
            Thread.Sleep(1000);

            List<ParaObject> l4 = pc.list(dogsType);
            Assert.IsTrue(l4.Count == 0);

            Assert.IsTrue(((Dictionary<string, object>) pc.getApp()["datatypes"]).ContainsValue(dogsType));
        }
 /// <summary>
 /// Links an object to this one in a many-to-many relationship.
 /// Only a link is created. Objects are left untouched.
 /// The type of the second object is automatically determined on read.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="id2">link to the object with this id</param>
 /// <returns>the id of the {@link com.erudika.para.core.Linker} object that is created</returns>
 public string link(ParaObject obj, string id2)
 {
     if (obj == null || obj.id == null || id2 == null)
     {
         return null;
     }
     string url = obj.getObjectURI() + "/links/" + id2;
     return (string) getEntity(invokePost(url, null), true);
 }
 /// <summary>
 /// Checks if a given object is linked to this one.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="toObj">the other object</param>
 /// <returns>true if linked</returns>
 public bool isLinked(ParaObject obj, ParaObject toObj)
 {
     if (obj == null || obj.id == null || toObj == null || toObj.id == null)
     {
         return false;
     }
     return isLinked(obj, toObj.type, toObj.id);
 }
 /// <summary>
 /// Checks if this object is linked to another.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">the other type</param>
 /// <param name="id2">the other id</param>
 /// <returns>true if the two are linked</returns>
 public bool isLinked(ParaObject obj, string type2, string id2)
 {
     if (obj == null || obj.id == null || type2 == null || id2 == null)
     {
         return false;
     }
     string url = obj.getObjectURI() + "/links/" + type2 + "/" + id2;
     return bool.Parse((string) getEntity(invokeGet(url, null), true));
 }
 /// <summary>
 /// Returns all objects linked to the given one. Only applicable to many-to-many relationships.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">type of linked objects to search for</param>
 /// <param name="pager">a Pager</param>
 /// <returns>a list of linked objects</returns>
 public List<ParaObject> getLinkedObjects(ParaObject obj, string type2, params Pager[] pager)
 {
     if (obj == null || obj.id == null || type2 == null)
     {
         return new List<ParaObject>(0);
     }
     string url = obj.getObjectURI() + "/links/" + type2;
     return getItems(getEntity(invokeGet(url, pagerToParams(pager)), true), pager);
 }
 /// <summary>
 /// Unlinks an object from this one.
 /// Only a link is deleted. Objects are left untouched.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">the other type</param>
 /// <param name="id2">the other id</param>
 public void unlink(ParaObject obj, string type2, string id2)
 {
     if (obj == null || obj.id == null || type2 == null || id2 == null)
     {
         return;
     }
     string url = obj.getObjectURI() + "/links/" + type2 + "/" + id2;
     invokeDelete(url, null);
 }
 /// <summary>
 /// Deletes all child objects permanently.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">the children's type.</param>
 public void deleteChildren(ParaObject obj, string type2)
 {
     if (obj == null || obj.id == null || type2 == null)
     {
         return;
     }
     var paramz = new Dictionary<string, object>();
     paramz["childrenonly"] = "true";
     string url = obj.getObjectURI() + "/links/" + type2;
     invokeDelete(url, paramz);
 }
 /////////////////////////////////////////////
 //                 PERSISTENCE
 /////////////////////////////////////////////
 /// <summary>
 /// Persists an object to the data store. If the object's type and id are given,
 /// then the request will be a PUT request and any existing object will be overwritten.
 /// </summary>
 /// <param name="obj">the domain object</param>
 /// <returns>the same object with assigned id or null if not created.</returns>
 public ParaObject create(ParaObject obj)
 {
     if (obj == null)
     {
         return null;
     }
     if (string.IsNullOrEmpty(obj.id) || string.IsNullOrEmpty(obj.type))
     {
         return (ParaObject) getEntity(invokePost(obj.type, obj), false);
     }
     else
     {
         return (ParaObject) getEntity(invokePut(obj.type + "/" + obj.id, obj), false);
     }
 }
 /// <summary>
 /// Deletes an object permanently.
 /// </summary>
 /// <param name="obj">the object to delete</param>
 public void delete(ParaObject obj)
 {
     if (obj == null)
     {
         return;
     }
     invokeDelete(obj.getObjectURI(), null);
 }
 /////////////////////////////////////////////
 //                 LINKS
 /////////////////////////////////////////////
 /// <summary>
 /// Count the total number of links between this object and another type of object.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">the other type of object</param>
 /// <returns>the number of links for the given object</returns>
 public long countLinks(ParaObject obj, string type2)
 {
     if (obj == null || obj.id == null || type2 == null)
     {
         return 0L;
     }
     var paramz = new Dictionary<string, object>();
     paramz["count"] = "true";
     var pager = new Pager();
     string url = obj.getObjectURI() + "/links/" + type2;
     getItems(getEntity(invokeGet(url, paramz), true), pager);
     return pager.count;
 }
 /// <summary>
 /// Updates an object permanently. Supports partial updates.
 /// </summary>
 /// <param name="obj">the object to update</param>
 /// <returns>the updated object</returns>
 public ParaObject update(ParaObject obj)
 {
     if (obj == null)
     {
         return null;
     }
     return (ParaObject) getEntity(invokePatch(obj.getObjectURI(), obj), false);
 }
 /// <summary>
 /// Unlinks all objects that are linked to this one.
 /// Only Linker objects are deleted, other objects are left untouched.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 public void unlinkAll(ParaObject obj)
 {
     if (obj == null || obj.id == null)
     {
         return;
     }
     string url = obj.getObjectURI() + "/links";
     invokeDelete(url, null);
 }
        public void testCRUD()
        {
            Assert.IsNull(pc.create(null));
            ParaObject t1 = pc.create(new ParaObject("test1", "tag"));
            t1["tag"] = "test1";
            Assert.IsNotNull(t1);

            Assert.IsNull(pc.read(null, null));
            Assert.IsNull(pc.read("", ""));

            ParaObject trID = pc.read(t1.id);
            Assert.IsNotNull(trID);
            Assert.IsNotNull(trID.timestamp);
            Assert.AreEqual(t1["tag"], trID["tag"]);

            ParaObject tr = pc.read(t1.type, t1.id);
            Assert.IsNotNull(tr);
            Assert.IsNotNull(tr.timestamp);
            Assert.AreEqual(t1["tag"], tr["tag"]);

            tr["count"] = (Int64)15;
            ParaObject tu = pc.update(tr);
            Assert.IsNull(pc.update(new ParaObject("null")));
            Assert.IsNotNull(tu);
            Assert.AreEqual(tu["count"], tr["count"]);
            Assert.IsNotNull(tu.updated);

            ParaObject s = new ParaObject();
            s.type = dogsType;
            s["foo"] = "bark!";
            s = pc.create(s);

            ParaObject dog = pc.read(dogsType, s.id);
            Assert.IsNotNull(dog["foo"]);
            Assert.AreEqual("bark!", dog["foo"]);

            pc.delete(t1);
            pc.delete(dog);
            Assert.IsNull(pc.read(tr.type, tr.id));
        }
 /// <summary>
 /// Searches through all linked objects in many-to-many relationships.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">type of linked objects to search for</param>
 /// <param name="field">the name of the field to target (within a nested field "nstd")</param>
 /// <param name="query">a query string</param> 
 /// <param name="pager">a Pager</param>
 /// <returns>a list of linked objects</returns>
 public List<ParaObject> findLinkedObjects(ParaObject obj, string type2, string field, string query, 
     params Pager[] pager)
 {
     if (obj == null || obj.id == null || type2 == null)
     {
         return new List<ParaObject>(0);
     }
     var paramz = new Dictionary<string, object>();
     paramz["field"] = field;
     paramz["q"] = string.IsNullOrEmpty(query) ? "*" : query;
     paramz.Concat(pagerToParams(pager));
     string url = obj.getObjectURI() + "/links/" + type2;
     return getItems(getEntity(invokeGet(url, paramz), true), pager);
 }
        public void testList()
        {
            List<ParaObject> cats = new List<ParaObject>();
            for (int i = 0; i < 3; i++)
            {
                ParaObject s = new ParaObject(catsType + i);
                s.type = catsType;
                cats.Add(s);
            }
            pc.createAll(cats);
            Thread.Sleep(1000);

            Assert.IsTrue(pc.list(null).Count == 0);
            Assert.IsTrue(pc.list("").Count == 0);

            List<ParaObject> list1 = pc.list(catsType);
            Assert.IsFalse(list1.Count == 0);
            Assert.AreEqual(3, list1.Count);
            Assert.AreEqual(typeof(ParaObject), list1[0].GetType());

            List<ParaObject> list2 = pc.list(catsType, new Pager(2));
            Assert.IsFalse(list2.Count == 0);
            Assert.AreEqual(2, list2.Count);

            List<string> nl = new List<string>(3);
            nl.Add(cats[0].id);
            nl.Add(cats[1].id);
            nl.Add(cats[2].id);
            pc.deleteAll(nl);

            Assert.IsTrue(((Dictionary<string, object>) pc.getApp()["datatypes"]).ContainsValue(catsType));
        }
 /// <summary>
 /// Returns all child objects linked to this object.
 /// </summary>
 /// <param name="obj">the object to execute this method on</param>
 /// <param name="type2">the type of children to look for</param>
 /// <param name="field">the field name to use as filter</param>
 /// <param name="term">the field value to use as filter</param>
 /// <param name="pager">a Pager</param>
 /// <returns>a list of ParaObject in a one-to-many relationship with this object</returns>
 public List<ParaObject> getChildren(ParaObject obj, string type2, string field, string term,
         params Pager[] pager)
 {
     if (obj == null || obj.id == null || type2 == null)
     {
         return new List<ParaObject>(0);
     }
     var paramz = new Dictionary<string, object>();
     paramz["childrenonly"] = "true";
     paramz["field"] = field;
     paramz["term"] = term;
     paramz.Concat(pagerToParams(pager));
     string url = obj.getObjectURI() + "/links/" + type2;
     return getItems(getEntity(invokeGet(url, paramz), true), pager);
 }
        public void testValidationConstraints()
        {
            // Validations
            string kittenType = "kitten";
            Dictionary<string, object> constraints = pc.validationConstraints();
            Assert.IsFalse(constraints.Count == 0);
            Assert.IsTrue(constraints.ContainsKey("app"));
            Assert.IsTrue(constraints.ContainsKey("user"));

            Dictionary<string, Dictionary<string, Dictionary<string, object>>> constraint =
                pc.validationConstraints("app");
            Assert.IsFalse(constraint.Count == 0);
            Assert.IsTrue(constraint.ContainsKey("app"));
            Assert.AreEqual(1, constraint.Count);

            pc.addValidationConstraint(kittenType, "paws", Constraint.required());
            constraint = pc.validationConstraints(kittenType);
            Assert.IsTrue(constraint[kittenType].ContainsKey("paws"));

            ParaObject ct = new ParaObject("felix");
            ct.type = kittenType;
            ParaObject ct2 = null;
            try {
                // validation fails
                ct2 = pc.create (ct);
            } catch { }

            Assert.IsNull(ct2);
            ct["paws"] = "4";
            Assert.IsNotNull(pc.create(ct));

            pc.removeValidationConstraint(kittenType, "paws", "required");
            constraint = pc.validationConstraints(kittenType);
            Assert.IsFalse(constraint.ContainsKey(kittenType));
        }
 /////////////////////////////////////////////
 //              Access Tokens
 /////////////////////////////////////////////
 /// <summary>
 /// Takes an identity provider access token and fetches the user data from that provider.
 /// A new {@link  User} object is created if that user doesn't exist.
 /// Access tokens are returned upon successful authentication using one of the SDKs from
 /// Facebook, Google, Twitter, etc.
 /// <b>Note:</b> Twitter uses OAuth 1 and gives you a token and a token secret.
 /// <b>You must concatenate them like this: <code>{oauth_token}:{oauth_token_secret}</code> and
 /// use that as the provider access token.</b>
 /// </summary>
 /// <returns>a user ParaObject or null if something failed</returns>
 /// <param name="provider">identity provider, e.g. 'facebook', 'google'...</param>
 /// <param name="providerToken">access token from a provider like Facebook, Google, Twitter</param>
 public ParaObject signIn(string provider, string providerToken)
 {
     if (!string.IsNullOrEmpty(provider) && !string.IsNullOrEmpty(providerToken)) {
         var credentials = new Dictionary<string, string>();
         credentials["appid"] = accessKey;
         credentials["provider"] = provider;
         credentials["token"] = providerToken;
         var res = getEntity(invokePost(JWT_PATH, credentials), true);
         var result = (res == null) ? null : JsonConvert.DeserializeObject
             <Dictionary<string, Dictionary<string, object>>>((string) res);
         if (result != null && result.ContainsKey("user") && result.ContainsKey("jwt")) {
             var jwtData = result["jwt"];
             var userData = result["user"];
             tokenKey = (string) jwtData["access_token"];
             tokenKeyExpires = (long) (jwtData["expires"] ?? -1);
             tokenKeyNextRefresh = (long) (jwtData["refresh"] ?? -1);
             var user = new ParaObject();
             user.setFields(userData);
             return user;
         }
         else
         {
             clearAccessToken();
         }
     }
     return null;
 }