com.microsoft.windowsazure.mobileservices.MobileServiceJsonTable.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.windowsazure.mobileservices.MobileServiceJsonTable.java

Source

/*
Copyright (c) Microsoft Open Technologies, Inc.
All Rights Reserved
Apache 2.0 License
    
   Licensed 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.
    
See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
 */
package com.microsoft.windowsazure.mobileservices;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidParameterException;
import java.util.Map;

import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * Represents a Mobile Service Table
 */
public final class MobileServiceJsonTable extends MobileServiceTableBase<TableJsonQueryCallback> {

    /**
     * Constructor for MobileServiceJsonTable
     * 
     * @param name
     *            The name of the represented table
     * @param client
     *            The MobileServiceClient used to invoke table operations
     */
    public MobileServiceJsonTable(String name, MobileServiceClient client) {
        initialize(name, client);
    }

    /**
     * Retrieves a set of rows from the table using a query
     * 
     * @param query
     *            The query used to retrieve the rows
     * @param callback
     *            Callback to invoke when the operation is completed
     */
    public void execute(final MobileServiceQuery<?> query, final TableJsonQueryCallback callback) {
        String url = null;
        try {
            String filtersUrl = URLEncoder.encode(query.toString().trim(), MobileServiceClient.UTF8_ENCODING);
            url = mClient.getAppUrl().toString() + TABLES_URL
                    + URLEncoder.encode(mTableName, MobileServiceClient.UTF8_ENCODING);

            if (filtersUrl.length() > 0) {
                url += "?$filter=" + filtersUrl + query.getRowSetModifiers();
            } else {
                String rowSetModifiers = query.getRowSetModifiers();
                if (rowSetModifiers.length() > 0) {
                    url += "?" + query.getRowSetModifiers().substring(1);
                }
            }

        } catch (UnsupportedEncodingException e) {
            if (callback != null) {
                callback.onCompleted(null, 0, e, null);
            }
            return;
        }

        executeGetRecords(url, callback);
    }

    /**
     * Looks up a row in the table and retrieves its JSON value.
     * 
     * @param id
     *            The id of the row
     * @param callback
     *            Callback to invoke after the operation is completed
     */
    public void lookUp(Object id, final TableJsonOperationCallback callback) {
        // Create request URL
        String url = null;
        try {
            url = mClient.getAppUrl().toString() + TABLES_URL
                    + URLEncoder.encode(mTableName, MobileServiceClient.UTF8_ENCODING) + "/"
                    + URLEncoder.encode(id.toString(), MobileServiceClient.UTF8_ENCODING);
        } catch (UnsupportedEncodingException e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        executeGetRecords(url, new TableJsonQueryCallback() {

            @Override
            public void onCompleted(JsonElement results, int count, Exception exception,
                    ServiceFilterResponse response) {
                if (callback != null) {
                    if (exception == null) {
                        if (results.isJsonArray()) { // empty result
                            callback.onCompleted(null,
                                    new MobileServiceException("A record with the specified Id cannot be found"),
                                    response);
                        } else { // Lookup result
                            callback.onCompleted(results.getAsJsonObject(), exception, response);
                        }
                    } else {
                        callback.onCompleted(null, exception, response);
                    }
                }
            }
        });
    }

    /**
     * Removes the Id property from a JsonObject
     * 
     * @param json
     *            The JsonObject to modify
     */
    private void removeIdFromJson(final JsonObject json) {
        // Remove id property if exists
        String[] idPropertyNames = new String[] { "id", "Id", "iD", "ID" };
        for (int i = 0; i < 4; i++) {
            String idProperty = idPropertyNames[i];
            if (json.has(idProperty)) {
                JsonElement idElement = json.get(idProperty);
                if (isValidTypeId(idElement) && idElement.getAsInt() != 0) {
                    throw new InvalidParameterException(
                            "The entity to insert should not have " + idProperty + " property defined");
                }

                json.remove(idProperty);
            }
        }
    }

    /**
     * Inserts a JsonObject into a Mobile Service Table
     * 
     * @param element
     *            The JsonObject to insert
     * @param callback
     *            Callback to invoke when the operation is completed
     * @throws InvalidParameterException
     */
    public void insert(final JsonObject element, final TableJsonOperationCallback callback) {

        try {
            removeIdFromJson(element);
        } catch (InvalidParameterException e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        String content = element.toString();

        ServiceFilterRequest post;
        try {
            post = new ServiceFilterRequestImpl(new HttpPost(mClient.getAppUrl().toString() + TABLES_URL
                    + URLEncoder.encode(mTableName, MobileServiceClient.UTF8_ENCODING)));
        } catch (UnsupportedEncodingException e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        try {
            post.setContent(content);
        } catch (Exception e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        executeTableOperation(post, new TableJsonOperationCallback() {

            @Override
            public void onCompleted(JsonObject jsonEntity, Exception exception, ServiceFilterResponse response) {
                if (callback != null) {
                    if (exception == null) {
                        JsonObject patchedJson = patchOriginalEntityWithResponseEntity(element, jsonEntity);

                        callback.onCompleted(patchedJson, exception, response);
                    } else {
                        callback.onCompleted(jsonEntity, exception, response);
                    }
                }
            }
        });
    }

    /**
     * Updates an element from a Mobile Service Table
     * 
     * @param element
     *            The JsonObject to update
     * @param callback
     *            Callback to invoke when the operation is completed
     */
    public void update(final JsonObject element, final TableJsonOperationCallback callback) {

        try {
            updateIdProperty(element);

            if (!element.has("id") || element.get("id").getAsInt() == 0) {
                throw new IllegalArgumentException(
                        "You must specify an id property with a valid value for updating an object.");
            }
        } catch (Exception e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        String content = element.toString();

        ServiceFilterRequest patch;
        try {
            patch = new ServiceFilterRequestImpl(new HttpPatch(mClient.getAppUrl().toString() + TABLES_URL
                    + URLEncoder.encode(mTableName, MobileServiceClient.UTF8_ENCODING) + "/"
                    + Integer.valueOf(getObjectId(element)).toString()));
        } catch (UnsupportedEncodingException e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        try {
            patch.setContent(content);
        } catch (Exception e) {
            if (callback != null) {
                callback.onCompleted(null, e, null);
            }
            return;
        }

        executeTableOperation(patch, new TableJsonOperationCallback() {

            @Override
            public void onCompleted(JsonObject jsonEntity, Exception exception, ServiceFilterResponse response) {
                if (callback != null) {
                    if (exception == null) {
                        JsonObject patchedJson = patchOriginalEntityWithResponseEntity(element, jsonEntity);
                        callback.onCompleted(patchedJson, exception, response);
                    } else {
                        callback.onCompleted(jsonEntity, exception, response);
                    }
                }
            }
        });
    }

    /**
     * Executes the query against the table
     * 
     * @param request
     *            Request to execute
     * @param callback
     *            Callback to invoke when the operation is completed
     */
    private void executeTableOperation(ServiceFilterRequest request, final TableJsonOperationCallback callback) {
        // Create AsyncTask to execute the operation
        new RequestAsyncTask(request, mClient.createConnection()) {
            @Override
            protected void onPostExecute(ServiceFilterResponse result) {
                if (callback != null) {
                    JsonObject newEntityJson = null;
                    if (mTaskException == null && result != null) {
                        String content = null;
                        content = result.getContent();

                        newEntityJson = new JsonParser().parse(content).getAsJsonObject();

                        callback.onCompleted(newEntityJson, null, result);

                    } else {
                        callback.onCompleted(null, mTaskException, result);
                        ;
                    }
                }
            }
        }.execute();
    }

    /**
     * Retrieves a set of rows from using the specified URL
     * 
     * @param query
     *            The URL used to retrieve the rows
     * @param callback
     *            Callback to invoke when the operation is completed
     */
    private void executeGetRecords(final String url, final TableJsonQueryCallback callback) {
        ServiceFilterRequest request = new ServiceFilterRequestImpl(new HttpGet(url));

        MobileServiceConnection conn = mClient.createConnection();
        // Create AsyncTask to execute the request and parse the results
        new RequestAsyncTask(request, conn) {
            @Override
            protected void onPostExecute(ServiceFilterResponse response) {
                if (callback != null) {
                    if (mTaskException == null && response != null) {
                        JsonElement results = null;

                        int count = 0;

                        try {
                            // Parse the results using the given Entity class
                            String content = response.getContent();
                            JsonElement json = new JsonParser().parse(content);

                            if (json.isJsonObject()) {
                                JsonObject jsonObject = json.getAsJsonObject();
                                // If the response has count property, store its
                                // value
                                if (jsonObject.has("results") && jsonObject.has("count")) { // inlinecount
                                    // result
                                    count = jsonObject.get("count").getAsInt();
                                    results = jsonObject.get("results");
                                } else {
                                    results = json;
                                }
                            } else {
                                results = json;
                            }
                        } catch (Exception e) {
                            callback.onCompleted(null, 0,
                                    new MobileServiceException("Error while retrieving data from response.", e),
                                    response);
                            return;
                        }

                        callback.onCompleted(results, count, null, response);

                    } else {
                        callback.onCompleted(null, 0, mTaskException, response);
                    }
                }
            }
        }.execute();
    }

    /**
     * Updates the JsonObject to have an id property
     * @param json
     *            the element to evaluate
     */
    private void updateIdProperty(final JsonObject json) throws IllegalArgumentException {
        for (Map.Entry<String, JsonElement> entry : json.entrySet()) {
            String key = entry.getKey();
            if (key.equalsIgnoreCase("id")) {
                JsonElement element = entry.getValue();
                if (isValidTypeId(element)) {
                    if (!key.equals("id")) {
                        //force the id name to 'id', no matter the casing 
                        json.remove(key);
                        // Create a new id property using the given property name
                        json.addProperty("id", entry.getValue().getAsNumber());
                    }
                    return;
                } else {
                    throw new IllegalArgumentException("The id must be numeric");
                }
            }
        }
    }

    /**
     * Validates if the id property is numeric.
     * @param element
     * @return
     */
    private boolean isValidTypeId(JsonElement element) {
        return element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber();
    }
}