package eu.musesproject.client.usercontexteventhandler; /* * #%L * musesclient * %% * Copyright (C) 2013 - 2014 HITEC * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import android.content.Context; import eu.musesproject.client.contextmonitoring.sensors.LocationSensor; import eu.musesproject.client.db.entity.Configuration; import eu.musesproject.client.db.entity.SensorConfiguration; import eu.musesproject.client.model.JSONIdentifiers; import eu.musesproject.client.model.RequestType; import eu.musesproject.client.model.decisiontable.Action; import eu.musesproject.client.utils.MusesUtils; import eu.musesproject.contextmodel.ContextEvent; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * @author christophstanik * * Class to transform action and context information to JSON */ public class JSONManager { private static final String TAG = JSONManager.class.getSimpleName(); /** * creates the JSON object that will be sent to the server via the {@link eu.musesproject.client.connectionmanager.ConnectionManager} * @param requestType {@link eu.musesproject.client.model.RequestType} * @param action {@link eu.musesproject.client.model.decisiontable.Action} * @param properties {@link java.util.Map} < String , String > * @param contextEvents {@link eu.musesproject.contextmodel.ContextEvent} * @return {@link org.json.JSONObject} */ public static JSONObject createJSON(String deviceId, String userName, int requestId, String requestType, Action action, Map<String, String> properties, List<ContextEvent> contextEvents) { JSONObject root = new JSONObject(); try { /* * request id */ root.put(JSONIdentifiers.REQUEST_IDENTIFIER, requestId); /* * request type */ root.put(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER, requestType); /* * device id */ root.put(JSONIdentifiers.AUTH_DEVICE_ID, deviceId); /* * username */ root.put(JSONIdentifiers.AUTH_USERNAME, userName); /* * action */ JSONObject actionJSON = new JSONObject(); if(action != null) { actionJSON.put(JSONIdentifiers.ACTION_TYPE, action.getActionType()); actionJSON.put(JSONIdentifiers.ACTION_TIMESTAMP, action.getTimestamp()); if(properties != null) { // create action properties JSONObject actionPropertiesJSON = createPropertiesJSONObject(properties); // add properties to action actionJSON.put(JSONIdentifiers.PROPERTIES_IDENTIFIER, actionPropertiesJSON); } } else { // if action is null, create the JSON as an update for the server. // So it has an default action that says, that there were ContextEvents // in the database which will be uploaded now actionJSON.put(JSONIdentifiers.ACTION_TYPE, "update"); // hard coded at this moment actionJSON.put(JSONIdentifiers.ACTION_TIMESTAMP, System.currentTimeMillis()); } // add action to root root.put(JSONIdentifiers.ACTION_IDENTIFIER, actionJSON); /* * sensor */ // create a JSON object for every sensor if(contextEvents != null) { JSONObject sensorRootJSON = new JSONObject(); for (ContextEvent contextEvent : contextEvents) { sensorRootJSON.put(contextEvent.getType(), createSensorJSONObject(contextEvent)); } // add sensor root JSON with n sensors to root root.put(JSONIdentifiers.SENSOR_IDENTIFIER, sensorRootJSON); } } catch (JSONException e) { e.printStackTrace(); } return root; } /** * creates a JSON object for the action properties * @param properties {@link java.util.Map < String , String >} * @return {@link org.json.JSONObject} * @throws org.json.JSONException */ private static JSONObject createPropertiesJSONObject(Map<String, String> properties) throws JSONException { JSONObject propertiesJSONObject = new JSONObject(); for (Entry<String, String> property : properties.entrySet()) { propertiesJSONObject.put(property.getKey(), property.getValue()); } return propertiesJSONObject; } /** * creates a JSON object for a Sensor. * @param contextEvent {@link eu.musesproject.contextmodel.ContextEvent} * @return {@link org.json.JSONObject} * @throws org.json.JSONException */ private static JSONObject createSensorJSONObject(ContextEvent contextEvent) throws JSONException { JSONObject sensorJSONObject = new JSONObject(); sensorJSONObject.put(ContextEvent.KEY_TYPE, contextEvent.getType()); sensorJSONObject.put(ContextEvent.KEY_TIMESTAMP, contextEvent.getTimestamp()); for (Entry<String, String> property : contextEvent.getProperties().entrySet()) { sensorJSONObject.put(property.getKey(), property.getValue()); } return sensorJSONObject; } /** * Method to create a response to the server which describes the user behavior. * The user behavior is defined as the decision a user took when a MUSES dialog popped up * @param deviceId deviceId (IMEI) * @param userName * @param userBehavior decision of the user from a muses dialog * @return {@link JSONObject} */ public static JSONObject createUserBehaviorJSON(String deviceId, String userName, String userBehavior, String decisionId) { JSONObject rootJSONObject = new JSONObject(); try { rootJSONObject.put(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER, RequestType.USER_ACTION); rootJSONObject.put(JSONIdentifiers.AUTH_DEVICE_ID, deviceId); rootJSONObject.put(JSONIdentifiers.AUTH_USERNAME, userName); rootJSONObject.put(JSONIdentifiers.DECISION_IDENTIFIER, decisionId); JSONObject userBehaviorJSONObject = new JSONObject(); userBehaviorJSONObject.put(JSONIdentifiers.ACTION_IDENTIFIER, userBehavior); rootJSONObject.put(JSONIdentifiers.USER_BEHAVIOR, userBehaviorJSONObject); } catch (JSONException e) { e.printStackTrace(); } return rootJSONObject; } /** * Method to create a login request to the server * @param userName login user name credential * @param password login user password credential * @param deviceId deviceId (IMEI) * @return {@link JSONObject} */ public static JSONObject createLoginJSON(String userName, String password, String deviceId) { JSONObject loginJSONObject = new JSONObject(); try { loginJSONObject.put(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER, RequestType.LOGIN); loginJSONObject.put(JSONIdentifiers.AUTH_USERNAME, userName); loginJSONObject.put(JSONIdentifiers.AUTH_PASSWORD, password); loginJSONObject.put(JSONIdentifiers.AUTH_DEVICE_ID, deviceId); } catch (JSONException e) { e.printStackTrace(); } return loginJSONObject; } /** * Method to create a JSON to logout the user * @param userName currently logged in user name * @param deviceId deviceId (IMEI) * @return JSONObject to logout the user */ public static JSONObject createLogoutJSON(String userName, String deviceId) { JSONObject logoutJSON = new JSONObject(); try { logoutJSON.put(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER, RequestType.LOGOUT); logoutJSON.put(JSONIdentifiers.AUTH_USERNAME, userName); logoutJSON.put(JSONIdentifiers.AUTH_DEVICE_ID, deviceId); } catch (JSONException e) { e.printStackTrace(); } return logoutJSON; } /** * Method to create a JSON object which will be used to request the client configuration * @param deviceId deviceId (IMEI) * @param osVersion current android version * @param userName login user name credential * @return {@link JSONObject} */ public static JSONObject createConfigSyncJSON(String deviceId, String osVersion, String userName) { JSONObject configSyncSONObject = new JSONObject(); try { configSyncSONObject.put(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER, RequestType.CONFIG_SYNC); configSyncSONObject.put(JSONIdentifiers.AUTH_USERNAME, userName); configSyncSONObject.put(JSONIdentifiers.AUTH_DEVICE_ID, deviceId); configSyncSONObject.put(JSONIdentifiers.OPERATING_SYSTEM_VERSION, osVersion); configSyncSONObject.put(JSONIdentifiers.OPERATING_SYSTEM, "Android"); } catch (JSONException e) { e.printStackTrace(); } return configSyncSONObject; } public static JSONObject createOpportunityJSON(String decisionId, String deviceId, String userName, String time, String revenueLossInEuros, String revenueLossDescription) { JSONObject opportunityJSONObject = new JSONObject(); try { opportunityJSONObject.put(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER, RequestType.OPPORTUNITY); opportunityJSONObject.put(JSONIdentifiers.DECISION_IDENTIFIER, decisionId); opportunityJSONObject.put(JSONIdentifiers.AUTH_DEVICE_ID, deviceId); opportunityJSONObject.put(JSONIdentifiers.AUTH_USERNAME, userName); opportunityJSONObject.put(JSONIdentifiers.OPPORTUNITY_TIME, time); opportunityJSONObject.put(JSONIdentifiers.OPPORTUNITY_LOSS_EUROS, revenueLossInEuros); opportunityJSONObject.put(JSONIdentifiers.OPPORTUNITY_LOSS_DESCRIPTION, revenueLossDescription); } catch (JSONException e) { e.printStackTrace(); } return opportunityJSONObject; } /** * Method to get true or false, whether the login was successful * @return boolean. login successful */ public static boolean getAuthResult(String jsonString) { boolean isLoginSuccessful = false; try { JSONObject requestJSON = new JSONObject(jsonString); String authResult = requestJSON.getString(JSONIdentifiers.AUTH_RESULT); if(authResult.equalsIgnoreCase("SUCCESS")) { isLoginSuccessful = true; } } catch (JSONException e) { e.printStackTrace(); } return isLoginSuccessful; } /** * * @param jsonString received json response from the server * @return the detailed status message, so that in case the login fails, * we can display meaningful information to the user, like username/password wrong or server offline */ public static String getAuthMessage(String jsonString) { String authMessage = ""; try { JSONObject requestJSON = new JSONObject(jsonString); authMessage = requestJSON.getString(JSONIdentifiers.AUTH_MESSAGE); } catch (JSONException e) { e.printStackTrace(); } return authMessage; } /** * Method to get a String that contains the {@link eu.musesproject.client.model.RequestType} from the server * @param jsonString String. JSON string from the server * @return String that contains a {@link eu.musesproject.client.model.RequestType} */ public static String getRequestType(String jsonString) { String requestType = null; try { JSONObject requestJSON = new JSONObject(jsonString); requestType = requestJSON.getString(JSONIdentifiers.REQUEST_TYPE_IDENTIFIER); } catch (JSONException e) { e.printStackTrace(); } return requestType; } /** * Method that returns the id of the request that was sent to the server. * * @param jsonString response from server * @return the request id */ public static int getRequestId(String jsonString) { int requestId = - 1; try { JSONObject responseJSON = new JSONObject(jsonString); JSONObject policyJSON = responseJSON.getJSONObject("muses-device-policy"); JSONObject fileJSON = policyJSON.getJSONObject("files"); JSONObject actionJSON = fileJSON.getJSONObject("action"); requestId = actionJSON.getInt("request_id"); } catch (JSONException e) { e.printStackTrace(); } return requestId; } /** * Method that returns the id of the request that was sent to the server. * * @param jsonString response from server * @return the request id */ public static int getRequestIdFromRequestJSON(String jsonString) { int requestId = - 1; try { JSONObject responseJSON = new JSONObject(jsonString); requestId = responseJSON.getInt("id"); // FIXME this is confusing, this attribute should be named request_id } catch (JSONException e) { e.printStackTrace(); } return requestId; } /** * Method that returns all received config items of each sensor * * @param jsonString response from server * @return List of config items */ public static List<SensorConfiguration> getSensorConfig(String jsonString) { List<SensorConfiguration> configList = new ArrayList<SensorConfiguration>(); try { JSONObject responseJSON = new JSONObject(jsonString); JSONObject sensorConfigJSON = responseJSON.getJSONObject("sensor-configuration"); JSONArray configProperties = sensorConfigJSON.getJSONArray("sensor-property"); for (int i = 0; i < configProperties.length(); i++) { JSONObject item = configProperties.getJSONObject(i); String sensorType = item.getString("sensor-type"); String key = item.getString("key"); String value = item.getString("value"); configList.add(new SensorConfiguration(sensorType, key, value)); } configList.addAll(addZoneConfigIfExists(jsonString)); } catch (JSONException e) { e.printStackTrace(); } return configList; } public static List<SensorConfiguration> addZoneConfigIfExists(String jsonString) { List<SensorConfiguration> zoneConfig = new ArrayList<SensorConfiguration>(); try { JSONObject responseJSON = new JSONObject(jsonString); JSONObject sensorConfigJSON = responseJSON.getJSONObject("zone-config"); JSONArray configProperties = sensorConfigJSON.getJSONArray("zone"); for (int i = 0; i < configProperties.length(); i++) { JSONObject item = configProperties.getJSONObject(i); String description = item.getString("description"); int zoneId = item.getInt("zoneId"); int radius = item.getInt("radius"); double latitude = item.getDouble("latitude"); double longitude = item.getDouble("longitud"); String sensorType = LocationSensor.TYPE; String key = "zone"; String value = description + ";" + zoneId + ";" + radius + ";" + latitude + ";" + longitude; zoneConfig.add(new SensorConfiguration(sensorType, key, value)); } } catch (JSONException e) { e.printStackTrace(); } return zoneConfig; } /** * Method that returns the id of the request that was sent to the server. * * @param jsonString response from server * @return true or false whether the silent mode should be active */ public static boolean isSilentModeActivated(String jsonString) { boolean isSilentModeActive = false; try { JSONObject responseJSON = new JSONObject(jsonString); JSONObject musesConfigJSON = responseJSON.getJSONObject("muses-config"); isSilentModeActive = musesConfigJSON.getBoolean("silent-mode"); } catch (JSONException e) { e.printStackTrace(); } return isSilentModeActive; } /** * Method that returns the id of the request that was sent to the server. * * @param jsonString response from server * @return true or false whether the silent mode should be active */ public static Configuration getConnectionConfiguration(String jsonString, Context context) { Configuration connectionConfig = new Configuration(); try { JSONObject responseJSON = new JSONObject(jsonString); JSONObject connectionConfigJSON = responseJSON.getJSONObject("connection-config"); connectionConfig.setServerIP(MusesUtils.getMusesConf()); connectionConfig.setServerPort(8443); connectionConfig.setServerServletPath("/commain"); connectionConfig.setServerContextPath("/server"); connectionConfig.setServerCertificate(MusesUtils.getCertificateFromSDCard(context)); connectionConfig.setClientCertificate(""); connectionConfig.setTimeout(connectionConfigJSON.getInt("timeout")); connectionConfig.setPollTimeout(connectionConfigJSON.getInt("poll_timeout")); connectionConfig.setSleepPollTimeout(connectionConfigJSON.getInt("sleep_poll_timeout")); connectionConfig.setPollingEnabled(connectionConfigJSON.getInt("polling_enabled")); connectionConfig.setLoginAttempts(connectionConfigJSON.getInt("login_attempts")); } catch (JSONException e) { e.printStackTrace(); } return connectionConfig; } /** * Method that returns the condition in the policy * * @param jsonString * @return */ public static String getPolicyCondition(String jsonString) { String cond = ""; try { JSONObject responseJSON = new JSONObject(jsonString); JSONObject filesJSON = responseJSON.getJSONObject("files"); JSONObject actionJSON = filesJSON.getJSONObject("action"); JSONObject denyJSON = actionJSON.getJSONObject("deny"); JSONObject conditionJSON = denyJSON.getJSONObject("condition"); cond = conditionJSON.toString(); } catch (JSONException e) { e.printStackTrace(); } return cond; } public static boolean isAccessbilityEnabled(String jsonString){ try { JSONObject requestJSON = new JSONObject(jsonString); JSONObject sensorsJSON = requestJSON.getJSONObject("sensor"); JSONObject deviceProtectionAttributesJSON = sensorsJSON.getJSONObject("CONTEXT_SENSOR_DEVICE_PROTECTION"); boolean accessbilityEnabled = deviceProtectionAttributesJSON.getBoolean("accessibilityenabled"); return accessbilityEnabled; } catch (JSONException e) { e.printStackTrace(); } return false; } public static long getScreenTimeout(String jsonString){ try { JSONObject requestJSON = new JSONObject(jsonString); JSONObject sensorsJSON = requestJSON.getJSONObject("sensor"); JSONObject deviceProtectionAttributesJSON = sensorsJSON.getJSONObject("CONTEXT_SENSOR_DEVICE_PROTECTION"); long screenTimeoutInSeconds = deviceProtectionAttributesJSON.getLong("screentimeoutinseconds"); return screenTimeoutInSeconds; } catch (JSONException e) { e.printStackTrace(); } return 0; } public static String getWifiEncryption(String jsonString){ try { JSONObject requestJSON = new JSONObject(jsonString); JSONObject sensorsJSON = requestJSON.getJSONObject("sensor"); JSONObject deviceProtectionAttributesJSON = sensorsJSON.getJSONObject("CONTEXT_SENSOR_CONNECTIVITY"); String wifiEncryption = deviceProtectionAttributesJSON.getString("wifiencryption"); return wifiEncryption; } catch (JSONException e) { e.printStackTrace(); } return null; } public static String getFilePath(String jsonString){ try { JSONObject requestJSON = new JSONObject(jsonString); JSONObject actionJSON = requestJSON.getJSONObject("action"); JSONObject propertiesJSON = actionJSON.getJSONObject("properties"); String path = propertiesJSON.getString("path"); return path; } catch (JSONException e) { e.printStackTrace(); return ""; } } public static String getActionType(String jsonString){ try { JSONObject requestJSON = new JSONObject(jsonString); JSONObject policyJSON = requestJSON.getJSONObject("muses-device-policy"); JSONObject fileJSON = policyJSON.getJSONObject("files"); JSONObject actionJSON = fileJSON.getJSONObject("action"); String actionType = actionJSON.getString("type"); return actionType; } catch (JSONException e) { e.printStackTrace(); return ""; } } }