Package almonds

Source Code of almonds.ParseObject$DeleteInBackgroundThread

package almonds;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

/**
* The <b>ParseObject</b> is a local representation of data that can be saved
* and retrieved from the Parse cloud.
*
* <p>
* The basic workflow for creating new data is to construct a new ParseObject,
* use put() to fill it with data, and then use save() to persist to the databa
*
* <p>
* The basic workflow for accessing existing data is to use a ParseQuery to
* specify which existing data to retrieve.
*
* @author js
*
*/
public class ParseObject {
  private static final String FIELD_CREATED_AT = "createdAt";
  private static final String FIELD_UPDATED_AT = "updatedAt";
  private boolean userClass = false;
  private String mClassName;
  private Hashtable<String, Object> mData;
  private ArrayList<String> mDataChangesKeys = new ArrayList<String>();

  /**
   * Creates a new ParseObject based upon a class name. If the class name is a
   * special type (e.g. for ParseUser), then the appropriate type of
   * ParseObject is returned.
   *
   * @param className
   *
   * @return
   */
  public static ParseObject create(String className) {
    return new ParseObject(className);
  }


  /**
   * Constructs a new ParseObject with no data in it. A ParseObject
   * constructed in this way will not have an objectId and will not persist to
   * the database until save() is called.
   *
   * Class names must be alphanumerical plus underscore, and start with a
   * letter. It is recommended to name classes in CamelCaseLikeThis.
   *
   * @param theClassName
   *            The className for this ParseObject.
   */
  public ParseObject(String theClassName)
  {
    if(theClassName.equals("_User"))
      userClass = true;

    mClassName = theClassName;
    mData = new Hashtable<String, Object>();

  }

  /**
   * Used to support a query that returns an object from Parse encoded with
   * JSON. This constructor will create itself from the JSON. This is probably
   * a poor method, especially if the JSON is mal-formed. A better approach
   * would be move the handling to ParseQuery, where it alone would
   * understands query responses from Parse.
   *
   * @param theClassName
   *            The className for this ParseObject
   * @param json
   *            JSON encoded response from Parse corresponding to a
   *            ParseObject
   */
  ParseObject(String theClassName, JSONObject json)
  {
    mClassName = theClassName;
    mData = new Hashtable<String, Object>();

    for (String name : JSONObject.getNames(json))
    {
      try
      {
        /*
         * Check for data types here. If the 'value' is JSONObject then
         * there's additional data type information.
         */
        if (json.get(name).getClass().getName().equals("org.json.JSONObject"))
        {
          JSONObject oType = (JSONObject) json.get(name);

          if (oType.get("__type").equals("Pointer"))
          {
            System.out.println("Found Pointer");
            put(name,
                new ParsePointer(oType.getString("className"), oType
                    .getString("objectId")));
          }
          else if (oType.get("__type").equals("Date"))
          {
            throw new UnsupportedOperationException();
          }
        }
        else
        {
          Object value = json.get(name); // the value associated with
                          // key 'name'

          /*
           * Check for special fields, createdAt and updatedAt, which
           * will be formatted and stored as Dates.
           */
          if (name.equals(FIELD_CREATED_AT) || name.equals(FIELD_UPDATED_AT))
          {
            value = javax.xml.bind.DatatypeConverter.parseDateTime((String) value)
                .getTime();
          }

          put(name, value);
        }
      }
      catch (JSONException e)
      {

      }
    }

  }

  /**
   * Whether this object has a particular key. Same as 'has'.
   *
   * @param key
   *            The key to check for
   * @return Returns whether this object contains the key
   */
  public boolean containsKey(String key)
  {
    return mData.containsKey(key);
  }

  /**
   * A private helper class to facilitate running a ParseObject delete
   * operation in the background.
   *
   * @author js
   *
   */
  class DeleteInBackgroundThread extends Thread
  {
    DeleteCallback mDeleteCallback;

    /**
     *
     * @param callback
     *            A function object of type DeleteCallback, whose method
     *            done will be called upon completion
     */
    DeleteInBackgroundThread(DeleteCallback callback)
    {
      mDeleteCallback = callback;
    }

    public void run()
    {
      ParseException exception = null;

      try
      {
        delete();
      }
      catch (ParseException e)
      {
        exception = e;
      }

      if (mDeleteCallback != null)
      {
        mDeleteCallback.done(exception);
      }
    }
  }

  /**
   * Deletes this object on the server in a background thread. Does nothing in
   * particular when the save completes. Use this when you don't care if the
   * delete works.
   */
  public void deleteInBackground()
  {
    deleteInBackground(null);
  }

  /**
   * Deletes this object on the server in a background thread. This is
   * preferable to using delete(), unless your code is already running from a
   * background thread.
   *
   * @param callback
   *            callback.done(e) is called when the save completes.
   */
  public void deleteInBackground(DeleteCallback callback)
  {
    DeleteInBackgroundThread thread = new DeleteInBackgroundThread(callback);
    thread.run();
  }

  /**
   * Deletes this object on the server. This does not delete or destroy the
   * object locally.
   *
   * @throws ParseException
   *             Throws an error if the object does not exist or if the
   *             internet fails.
   *
   */
  public void delete() throws ParseException
  {
    try
    {
      HttpClient httpclient = new DefaultHttpClient();
      String path = Parse.getParseAPIUrlClasses() + mClassName + "/"
          + getObjectId();
      if(userClass == true)
        path = Parse.getParseAPIUrlUsers();
      HttpDelete httpdelete = new HttpDelete(path);
      httpdelete.addHeader("X-Parse-Application-Id", Parse.getApplicationId());
      httpdelete.addHeader("X-Parse-REST-API-Key", Parse.getRestAPIKey());

      HttpResponse httpresponse = httpclient.execute(httpdelete);

      ParseResponse response = new ParseResponse(httpresponse);

      if (!response.isFailed())
      {
        // delete was successful
      }
      else
      {
        throw response.getException();
      }
    }
    catch (ClientProtocolException e)
    {
      throw ParseResponse.getConnectionFailedException(e.getMessage());
    }
    catch (IOException e)
    {
      throw ParseResponse.getConnectionFailedException(e.getMessage());
    }
  }

  /**
   * Accessor to the class name.
   *
   * @return
   */
  public String getClassName()
  {
    return mClassName;
  }

  /**
   * Accessor to the object id. An object id is assigned as soon as an object
   * is saved to the server. The combination of a className and an objectId
   * uniquely identifies an object in your application.
   *
   * @return The object id.
   */
  public String getObjectId()
  {
    return (String) mData.get("objectId");
  }

  /**
   * Setter for the object id. In general you do not need to use this.
   * However, in some cases this can be convenient. For example, if you are
   * serializing a ParseObject yourself and wish to recreate it, you can use
   * this to recreate the ParseObject exactly.
   *
   * @param objectId
   */
  public void setObjectId(String objectId) {
    mData.put("objectId", objectId);
    mDataChangesKeys.add("objectId");
  }

  public void setCreatedAt(String createdAt) {
    mData.put("createdAt", createdAt);
    mDataChangesKeys.add("objectId");
  }

  /**
   * Access a ParsePointer value.
   *
   * @param key
   *            The key to access the value for.
   * @return Returns null if there is no such key or if it is not a
   *         ParsePointer.
   */
  public ParsePointer getParsePointer(String key)
  {
    Object value = get(key);

    // test for no such key or not a ParsePointer

    if (value == null || value.getClass() != ParsePointer.class)
      return null;

    return (ParsePointer) value;
  }

  /**
   * Creates and returns a new ParsePointer object that points to the object
   * it's called on. Use when other objects need to point to *this* object.
   *
   * @return A ParsePointer object set to point to this object.
   */
  public ParsePointer getPointer()
  {
    return new ParsePointer(mClassName, getObjectId());
  }

  /**
   * Access a string value.
   *
   * @param key
   *            The key to access the value for.
   * @return Returns null if there is no such key or if it is not a String.
   */
  public String getString(String key)
  {
    Object value = get(key);

    // test for no such key or value not a string

    if (value == null || value.getClass() != String.class)
      return null;

    return (String) value;
  }

  /**
   * Access a boolean value.
   *
   * @param key
   *            The key to access the value for.
   * @return Returns false if there is no such key or if it is not a boolean.
   */
  public Boolean getBoolean(String key)
  {
    Object value = get(key);

    // test for no such key or value not a string

    if (value == null || value.getClass() != Boolean.class)
      return null;

    return (Boolean) value;
  }

  /**
   * Encapsulates access to the HashTable that stores key/value pairs stored
   * by this Object
   *
   * @param key
   *            The key to access the value for
   * @return Returns null if there is no such key
   */
  public Object get(String key) {
    return mData.get(key);
  }

  /**
   * Access a Date value.
   *
   * @param key
   *            The key to access the value for.
   * @return Returns null if there is no such key or if it is not a Date.
   */
  public Date getDate(String key) {
    return getCalendarDate(key).getTime();
  }
 
  public Calendar getCalendarDate(String key){
    JSONObject value = (JSONObject) get(key);
    Object ob = null;
    try {
      ob = value.get("iso");
    } catch (JSONException e) {
      // XXX report error
      return null;
    }   
    return parseDateFromString(ob.toString());
  }
 
  private static Calendar parseDateFromString(String dateString){
    int year = Integer.parseInt(dateString.substring(0, 4));
    int month = Integer.parseInt(dateString.substring(5, 7)) - 1;
    int day = Integer.parseInt(dateString.substring(8, 10));
    int hour = Integer.parseInt(dateString.substring(11, 13));
    int minute = Integer.parseInt(dateString.substring(14, 16));
    int second = Integer.parseInt(dateString.substring(17, 19));
    int milisecond = Integer.parseInt(dateString.substring(20, 23));
    Calendar cal = Calendar.getInstance();
    cal.set(year, month, day, hour, minute, second);
    cal.set(Calendar.MILLISECOND, milisecond);
    return cal;
  }
 
  private static String parseStringFromDate(Calendar cal){   
    String parsedDate = "";
    parsedDate += cal.get(Calendar.YEAR) + "-";
    parsedDate += repairIfShorter((cal.get(Calendar.MONTH)+1) + "") + "-";
    parsedDate += repairIfShorter(cal.get(Calendar.DAY_OF_MONTH) + "") + "T";
    parsedDate += repairIfShorter(cal.get(Calendar.HOUR_OF_DAY) + "") + ":";
    parsedDate += repairIfShorter(cal.get(Calendar.MINUTE) + "") + ":";
    parsedDate += repairIfShorter(cal.get(Calendar.SECOND) + "") + ".";
    parsedDate += repairIfShorter(cal.get(Calendar.MILLISECOND) + "", 3) + "Z";
    //return "{"+ '"' +"__type" + '"' + ":"+'"' + "Date" + '"' +","+ '"' + "iso"+ '"' + ":"+ '"' + parsedDate + '"' +"}";
    return parsedDate;
  }
 
  private static String repairIfShorter(String str, int than){
    while(str.length() < than)
      str = "0"+str;
    return str;
  }
 
  private static String repairIfShorter(String str){
    return repairIfShorter(str, 2);
  }

  /**
   * Access a long value.
   *
   * @param key
   *            The key to access the value for.
   * @return Returns null if there is no such key or if it is not a long.
   */
  public Long getLong(String key) {
    Object value = get(key);

    // test for no such key or value not a long

    if (value == null || value.getClass() != Long.class)
      return null;

    return (Long) value;
  }
 
  /**
   *
   * @param key The key to access the value for.
   * @return Returns null if there is no such key or if it is not an integer.
   */
  public Integer getInt(String key){
    Object value = get(key);

    // test for no such key or value not a long

    if (value == null || value.getClass() != Integer.class)
      return null;
   
    return (Integer) value;   
  }
 
  /**
   *
   * @param key  The key to access the value for.
   * @return Returns null if there is no such key or if it is not a double.
   */
  public Double getDouble(String key){
    Object value = get(key);
   
    try {
      return (Double) value;
    } catch (ClassCastException e) {
      return null;
    }   
  }

  /**
   * Add a key-value pair to this object. It is recommended to name keys in
   * partialCamelCaseLikeThis.
   *
   * @param key
   *            Keys must be alphanumerical plus underscore, and start with a
   *            letter.
   * @param value
   *            Values may be numerical, String, JSONObject, JSONArray,
   *            JSONObject.NULL, or other ParseObjects. value may not be null.
   */
  public void put(String key, Object value) {
    mData.put(key, value);
    mDataChangesKeys.add(key);
  }

  protected void setSessionToken(String sessionToken){
   
  }
 
  /*
   * TODO remove it from ParseObject
   */
  public String getSessionToken(){
    return null;
  }
 
  public void save(SaveCallback callback){
    ParseException e = null;   
    try {
      save();
    } catch (ParseException e1) {
      e = e1;
    }
    callback.done(e);
  }

  /**
   * Saves this object to the server. Typically, you should use
   * saveInBackground(com.parse.SaveCallback) instead of this, unless you are
   * managing your own threading.
   *
   * @throws ParseException
   *             Throws an exception if the server is inaccessible.
   */
  public void save() throws ParseException {
    if(mData.get("objectId") == null)
      saveAsNew();
    else
      update();
   
 

  private void update() throws ParseException {
    try {
      HttpClient httpclient = new DefaultHttpClient();
      String path = Parse.getParseAPIUrlClasses() + mClassName;
      if(userClass == true)
        path = Parse.getParseAPIUrlUsers();
      path += "/" + mData.get("objectId");

      HttpPut httpPut = new HttpPut(path);
      httpPut.addHeader("X-Parse-Application-Id", Parse.getApplicationId());
      httpPut.addHeader("X-Parse-REST-API-Key", Parse.getRestAPIKey());
      if(userClass == true)
        httpPut.addHeader("X-Parse-Session-Token", getSessionToken());
      httpPut.addHeader("Content-Type", "application/json");

      httpPut.setEntity(new StringEntity(toJSONObjectUpdateData().toString()));
      HttpResponse httpresponse = httpclient.execute(httpPut);
      ParseResponse response = new ParseResponse(httpresponse);
      if (!response.isFailed()) {
        JSONObject jsonResponse = response.getJsonObject();
        if (jsonResponse == null)
          throw response.getException();
       
        try  {
          setCreatedAt(jsonResponse.getString("updatedAt"));
        } catch (JSONException e) {
          throw new ParseException(
              ParseException.INVALID_JSON,
              "Although Parse reports object successfully saved, the response was invalid.",
              e);
        }

      } else {   
        throw response.getException();
      }
    } catch (IOException e) {
      throw ParseResponse.getConnectionFailedException(e);
    }
  }


  private void saveAsNew() throws ParseException {
    try  {
      HttpClient httpclient = new DefaultHttpClient();
      String path = Parse.getParseAPIUrlClasses() + mClassName;
      if(userClass == true)
        path = Parse.getParseAPIUrlUsers();
      HttpPost httppost = new HttpPost(path);
      httppost.addHeader("X-Parse-Application-Id", Parse.getApplicationId());
      httppost.addHeader("X-Parse-REST-API-Key", Parse.getRestAPIKey());
      httppost.addHeader("Content-Type", "application/json");
     
      httppost.setEntity(new StringEntity(toJSONObject().toString()));
      HttpResponse httpresponse = httpclient.execute(httppost);

      ParseResponse response = new ParseResponse(httpresponse);
      if (!response.isFailed()) {
        JSONObject jsonResponse = response.getJsonObject();

        if (jsonResponse == null)
          throw response.getException();
       

        try  {
          setObjectId(jsonResponse.getString("objectId"));
          setCreatedAt(jsonResponse.getString("createdAt"));
          try {
            setSessionToken(jsonResponse.getString("sessionToken"));
          } catch (Exception e) {
           
          }
        } catch (JSONException e) {
          throw new ParseException(
              ParseException.INVALID_JSON,
              "Although Parse reports object successfully saved, the response was invalid.",
              e);
        }

      } else {   
        throw response.getException();
      }
    } catch (ClientProtocolException e) {
      throw ParseResponse.getConnectionFailedException(e);
    } catch (IOException e) {
      throw ParseResponse.getConnectionFailedException(e);
    }
  }

  /**
   * A private helper class to facilitate running a ParseObject save operation
   * in the background.
   *
   * @author js
   *
   */
  class SaveInBackgroundThread extends Thread {
    SaveCallback mSaveCallback;

    /**
     *
     * @param callback
     *            A function object of type Savecallback, whose method done
     *            will be called upon completion
     */
    SaveInBackgroundThread(SaveCallback callback) {
      mSaveCallback = callback;
    }

    public void run() {
      ParseException exception = null;

      try {
        save();
      } catch (ParseException e) {
        exception = e;
      }

      if (mSaveCallback != null) {
        mSaveCallback.done(exception);
      }
    }
  }

  /**
   * Saves this object to the server in a background thread. This is
   * preferable to using save(), unless your code is already running from a
   * background thread.
   *
   * @param callback
   *            callback.done(e) is called when the save completes.
   */
  public void saveInBackground(SaveCallback callback) {
    SaveInBackgroundThread t = new SaveInBackgroundThread(callback);
    t.start();
  }

  /**
   * Saves this object to the server in a background thread. Use this when you
   * do not have code to run on completion of the push.
   */
  public void saveInBackground() {
    saveInBackground(null);
  }

  private JSONObject toJSONObject() {
    JSONObject jo = new JSONObject();
    for (String key : mData.keySet())
      addElementToJSONObject(jo, key);

    return jo;
  }
 
  private JSONObject toJSONObjectUpdateData(){
    JSONObject jo = new JSONObject();
    for(int i = 0; i < mDataChangesKeys.size(); i++)
      addElementToJSONObject(jo, mDataChangesKeys.get(i));
   
    mDataChangesKeys.clear();
    return jo;
  }
 
  private void addElementToJSONObject(JSONObject jo, String key){
    try {     
      Object obj = get(key);
      if(obj instanceof Calendar){
        obj = getDateJSONObject((Calendar) obj);
      }else if(obj instanceof Date){
        Calendar cal = Calendar.getInstance();
        cal.setTime((Date) obj);
        obj = getDateJSONObject(cal);
      }
      jo.put(key, obj);
    } catch (JSONException e) {
     
    }   
  }
 
  static JSONObject getDateJSONObject(Calendar cal) throws JSONException{
    JSONObject obj = new JSONObject();
    obj.put("__type", "Date");
    obj.put("iso", parseStringFromDate(cal));
    return obj;
  }
 

  /**
   * This reports time as the server sees it, so that if you make changes to a
   * ParseObject, then wait a while, and then call save(), the updated time
   * will be the time of the save() call rather than the time the object was
   * changed locally.
   *
   * @return The last time this object was updated on the server.
   */
  public Date getUpdatedAt() {
    return getDate(FIELD_UPDATED_AT);
  }

  /**
   * This reports time as the server sees it, so that if you create a
   * ParseObject, then wait a while, and then call save(), the creation time
   * will be the time of the first save() call rather than the time the object
   * was created locally.
   *
   * @return The first time this object was saved on the server.
   */
  public Date getCreatedAt() {
    return getDate(FIELD_CREATED_AT);
  }

  /**
   * Decides if the calling ParseObject and the parameter ParseObject have the
   * same Parse Id.
   *
   * @param asThisObject
   *            Parse Object to compare with
   * @return True if the Ids of the two objects are equal, false otherwise
   */
  public boolean hasSameId(ParseObject asThisObject) {
    return this.getObjectId().equals(asThisObject.getObjectId());
  }
}
TOP

Related Classes of almonds.ParseObject$DeleteInBackgroundThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.