/*
Copyright (c) 2013 Cloudbase.io Limited
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.
*/
package com.cloudbase;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.cloudbase.datacommands.CBDataAggregationCommand;
import com.cloudbase.datacommands.CBSearchCondition;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/*! \mainpage cloudbase.io Java Helper Class Reference
*
* \section intro_sec Introduction
*
* Copyright (c) 2013 Cloudbase.io Limited
*
* 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.
*
* \section install_sec Getting Started
*
* The cloudbase.io Java helper class compiles to .jar library.
* Make sure the library is included in your project. There are two places where we need to call it from the
* project properties
*/
/**
* The main CBHelper class. All of the methods interacting with the cloudbase.io APIs are part of this class.
*
* This class requires the appCode, appSecret and password
* properties set. appCode and appSecret are handed to the class in the constructor and the password can be
* set using the setPassword setter.
*
* This library depends on the Gson library by google. This is used to serialise and de-serialise objects to be
* sent to the APIs. This library was built on top of the Gson 2.2.1. Make sure the jar file is available in your
* classpath
* @author Stefano Buliani
*/
public class CBHelper implements CBHelperResponder {
// application settings to connect to cloudbase.io
private String appCode;
private String appSecret;
private String password;
// whether to use the https apis. This should be set to "true" by default.
private boolean https;
// whether the APIs require user authentication. and the current application
// username and password
private boolean userAuthentication;
private String authUsername;
private String authPassword;
// The current location variable to be attached to requests to the CloudBase apis
private boolean useLocation;
private CBLocation currentLocation;
private String sessionId;
private CBDeviceInfo deviceInfo;
// this is used when downloading attachments from the CloudBase - temporary files
// are saved in the application files folder and handed back to the application
private String temporaryFilesPath;
private CBHelperResponder defaultQueueResponder;
private boolean debugMode;
private String apiURL = "api.cloudbase.io";
private static final String defaultLogCategory = "DEFAULT";
public static final String logTag = "CBHELPER";
private boolean deviceRegistered;
private static Gson jsonParser = new GsonBuilder().disableHtmlEscaping().create();//new Gson();
/**
* Creates a new instance of CBHelper and initializes the main properties to their default values.
* @param code The application code generated by cloudbase.io when the application is registered (test-application)
* @param uniq The unique code generated by cloudbase.io when the application is registered (8a159fe6e4493d4b9a56d4aa580953a2)
* @param activity The main activity from the application. This is used to get Context variables, specifically the Cache directory
* @throws Exception
*/
public CBHelper(String code, String uniq, CBDeviceInfo info)
{
this.appCode = code;
this.appSecret = uniq;
this.userAuthentication = false;
this.https = true;
this.debugMode = false;
this.deviceInfo = info;
this.deviceRegistered = false;
this.temporaryFilesPath = info.getTemporaryFilesPath();
//Log.d(logTag, "CBHelper initialized");
}
/**
* Logs an event to the cloudbase.io application log
* @param logLine The content of the line to be logged
*/
public void logEvent(String logLine) {
this.log(logLine, CBLogLevel.EVENT, null, null, false);
}
/**
* Logs an event to the cloudbase.io application log
* @param logLine The content of the line to be Logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void logEvent(String logLine, String category) {
this.log(logLine, CBLogLevel.EVENT, category, null, false);
}
/**
* Logs an event to the cloudbase.io application log
* @param logLine The content of the line to be Logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
*/
public void logEvent(String logLine, String category, CBHelperResponder responder) {
this.log(logLine, CBLogLevel.EVENT, category, responder, false);
}
/**
* Logs a fatal exception to the cloudbase.io application log
* @param logLine The content of the line to be logged
*/
public void logFatal(String logLine) {
this.log(logLine, CBLogLevel.FATAL, null, null, false);
}
/**
* Logs a fatal exception to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void logFatal(String logLine, String category) {
this.log(logLine, CBLogLevel.FATAL, category, null, false);
}
/**
* Logs a fatal exception to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
*/
public void logFatal(String logLine, String category, CBHelperResponder responder) {
this.log(logLine, CBLogLevel.FATAL, category, responder, false);
}
/**
* Logs an error to the cloudbase.io application log
* @param logLine The content of the line to be logged
*/
public void logError(String logLine) {
this.log(logLine, CBLogLevel.ERROR, null, null, false);
}
/**
* Logs an error to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void logError(String logLine, String category) {
this.log(logLine, CBLogLevel.ERROR, category, null, false);
}
/**
* Logs an error to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
*/
public void logError(String logLine, String category, CBHelperResponder responder) {
this.log(logLine, CBLogLevel.ERROR, category, responder, false);
}
/**
* Logs a warning to the cloudbase.io application log
* @param logLine The content of the line to be logged
*/
public void logWarning(String logLine) {
this.log(logLine, CBLogLevel.WARNING, null, null, false);
}
/**
* Logs a warning to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void logWarning(String logLine, String category) {
this.log(logLine, CBLogLevel.WARNING, category, null, false);
}
/**
* Logs a warning to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
*/
public void logWarning(String logLine, String category, CBHelperResponder responder) {
this.log(logLine, CBLogLevel.WARNING, category, responder, false);
}
/**
* Logs an information message to the cloudbase.io application log
* @param logLine The content of the line to be logged
*/
public void logInfo(String logLine) {
this.log(logLine, CBLogLevel.INFO, null, null, false);
}
/**
* Logs an information message to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void logInfo(String logLine, String category) {
this.log(logLine, CBLogLevel.INFO, category, null, false);
}
/**
* Logs an information message to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
*/
public void logInfo(String logLine, String category, CBHelperResponder responder) {
this.log(logLine, CBLogLevel.INFO, category, responder, false);
}
/**
* Logs a debug message to the cloudbase.io application log
* @param logLine The content of the line to be logged
*/
public void logDebug(String logLine) {
this.log(logLine, CBLogLevel.DEBUG, null, null, false);
}
/**
* Logs a debug message to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void logDebug(String logLine, String category) {
this.log(logLine, CBLogLevel.DEBUG, category, null, false);
}
/**
* Logs a debug message to the cloudbase.io application log
* @param logLine The content of the line to be logged
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
*/
public void logDebug(String logLine, String category, CBHelperResponder responder) {
this.log(logLine, CBLogLevel.DEBUG, category, responder, false);
}
/**
* Send a line to the log on the cloudbase.io application log.
*
* @param logLine The content of the log line
* @param level The severity of the log line, a CBLogLevel value
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
*/
public void log(String logLine, CBLogLevel level, String category) {
this.log(logLine, level, category, null, false);
}
/**
* Send a line to the log on the cloudbase.io application log.
*
* @param logLine The content of the log line
* @param level The severity of the log line, a CBLogLevel value
* @param category The category of the log line. This is a free text string and can be used to separate different
* sections of the application and events
* @param responder A responder to handle the return value from the cloudbase.io APIs. This is an optional parameter
* and can be sent as null
* @param shouldQueue whether the request should be queued if connectivity is not available
*/
public void log(String logLine, CBLogLevel level, String category, CBHelperResponder responder, boolean shouldQueue) {
String url = this.getUrl() + this.appCode + "/log";
// Create the log object
Hashtable logData = new Hashtable();
logData.put("category", (category == null?CBHelper.defaultLogCategory:category));
logData.put("level", level.toString());
logData.put("device_name", this.deviceInfo.getDeviceName());
logData.put("device_model", this.deviceInfo.getDeviceModel());
logData.put("log_line", logLine);
Hashtable preparedPost = this.preparePostParams(logData, null);
this.startRequest(url, "log", null, preparedPost, null, responder, shouldQueue);
}
/**
* Sends cloudbase.io the name of the newly opened screen. This data is used to then generate the usage
* flow analytics and show how people interact with your application
* This API request will always be queued
* @param screenName The unique name assigned to the opened view
*/
public void logNavigation(String screenName) {
String url = this.getUrl() + this.appCode + "/lognavigation";
Hashtable logData = new Hashtable();
logData.put("session_id", this.sessionId);
logData.put("screen_name", screenName);
Hashtable preparedPost = this.preparePostParams(logData, null);
this.startRequest(url, "log", null, preparedPost, null, null, true);
}
/**
* Inserts the given object in a cloudbase.io collection. If the collection does not exist it is automatically created.
* Similarly if the data structure of the given object is different from documents already present in the collection
* the structure is automatically altered to accommodate the new object.
* The system will automatically try to serialize any object sent to this function. However, we recommend you use
* the simplest possible objects to hold data if not a Map or Array directly.
* Once the call to the APIs is completed the responder is called.
* This API request will not be queued
* @param document The object to be inserted
* @param collection The name of the collection the document should be inserted into
*/
public void insertDocument(Object document, String collection) {
insertDocument(document, collection, null, null);
}
/**
* Inserts the given object in a cloudbase.io collection. If the collection does not exist it is automatically created.
* Similarly if the data structure of the given object is different from documents already present in the collection
* the structure is automatically altered to accommodate the new object.
* The system will automatically try to serialize any object sent to this function. However, we recommend you use
* the simplest possible objects to hold data if not a Map or Array directly.
* Once the call to the APIs is completed the responder is called.
* @param document The object to be inserted
* @param collection The name of the collection the document should be inserted into
* @param shouldQueue whether the request should be queued if connectivity is not available
*/
public void insertDocument(Object document, String collection, boolean shouldQueue) {
insertDocument(document, collection, null, null, shouldQueue);
}
/**
* Inserts the given object in a cloudbase.io collection. If the collection does not exist it is automatically created.
* Similarly if the data structure of the given object is different from documents already present in the collection
* the structure is automatically altered to accommodate the new object.
* The system will automatically try to serialize any object sent to this function. However, we recommend you use
* the simplest possible objects to hold data if not a Map or Array directly.
* Once the call to the APIs is completed the responder is called.
* This API request will not be queued
* @param document The object to be inserted
* @param collection The name of the collection the document should be inserted into
* @param responder The CBHelperResponder object to handle the response from the cloudbase.io APIs
*/
public void insertDocument(Object document, String collection, CBHelperResponder responder) {
insertDocument(document, collection, null, responder);
}
/**
* Inserts the given object in a cloudbase.io collection. If the collection does not exist it is automatically created.
* Similarly if the data structure of the given object is different from documents already present in the collection
* the structure is automatically altered to accommodate the new object.
* The system will automatically try to serialize any object sent to this function. However, we recommend you use
* the simplest possible objects to hold data if not a Map or Array directly.
* Once the call to the APIs is completed the responder is called.
* @param document The object to be inserted
* @param collection The name of the collection the document should be inserted into
* @param responder The CBHelperResponder object to handle the response from the cloudbase.io APIs
* @param shouldQueue whether the request should be queued if connectivity is not available
*/
public void insertDocument(Object document, String collection, CBHelperResponder responder, boolean shouldQueue) {
insertDocument(document, collection, null, responder, shouldQueue);
}
/**
* Inserts the given object in a cloudbase.io collection. If the collection does not exist it is automatically created.
* Similarly if the data structure of the given object is different from documents already present in the collection
* the structure is automatically altered to accommodate the new object.
* The system will automatically try to serialize any object sent to this function. However, we recommend you use
* the simplest possible objects to hold data if not a Map or Array directly.
* Once the call to the APIs is completed the responder is called.
* This API request will not be queued
* @param document The object to be inserted
* @param collection The name of the collection the document should be inserted into
* @param attachments An ArrayList of of File objects to be attached to the record. File IDs will be stored in the additional column
* cb_files
* @param responder The CBHelperResponder object to handle the response from the cloudbase.io APIs
*/
public void insertDocument(Object document, String collection, ArrayList attachments, CBHelperResponder responder) {
this.insertDocument(document, collection, attachments, responder, false);
}
@SuppressWarnings("unchecked")
/**
* Inserts the given object in a cloudbase.io collection. If the collection does not exist it is automatically created.
* Similarly if the data structure of the given object is different from documents already present in the collection
* the structure is automatically altered to accommodate the new object.
* The system will automatically try to serialize any object sent to this function. However, we recommend you use
* the simplest possible objects to hold data if not a Map or Array directly.
* Once the call to the APIs is completed the responder is called.
* @param document The object to be inserted
* @param collection The name of the collection the document should be inserted into
* @param attachments An ArrayList of of File objects to be attached to the record. File IDs will be stored in the additional column
* cb_files
* @param responder The CBHelperResponder object to handle the response from the cloudbase.io APIs
* @param shouldQueue whether the request should be queued if connectivity is not available
*/
public void insertDocument(Object document, String collection, ArrayList attachments, CBHelperResponder responder, boolean shouldQueue) {
// We need to insert a List as the cloudbase.io APIs expect an array of objects to the
// insert APIs - this way we can insert multiple objects at the same time. If it is not a List
// then create a new List and insert the given object in it.
List