diff --git a/src/main/java/com/jaguarlandrover/rvi/DlinkReceivePacket.java b/src/main/java/com/jaguarlandrover/rvi/DlinkReceivePacket.java index bca90b5..3edc91f 100644 --- a/src/main/java/com/jaguarlandrover/rvi/DlinkReceivePacket.java +++ b/src/main/java/com/jaguarlandrover/rvi/DlinkReceivePacket.java @@ -34,13 +34,15 @@ class DlinkReceivePacket extends DlinkPacket /** * The Service used to create the request params. */ - private transient Service mService; + @SerializedName("data") + private Service mService; +// private transient Service mService; /** * The service is converted to a json string, then base64 encoded to be embedded in the packet's json. */ - @SerializedName("data") - private String mData; +// @SerializedName("data") +// private String mData; /** * Instantiates a new Dlink receive packet. @@ -57,8 +59,11 @@ class DlinkReceivePacket extends DlinkPacket super(Command.RECEIVE); mMod = "proto_json_rpc"; - mService = service; // TODO: With this paradigm, if one of the parameters of mService changes, mData string will still be the same. - mData = mService.jsonString();//Base64.encodeToString(mService.jsonString().getBytes(), Base64.DEFAULT); + mService = service; + + + // TODO: With this paradigm, if one of the parameters of mService changes, mData string will still be the same. + //mData = mService.jsonString();//Base64.encodeToString(mService.jsonString().getBytes(), Base64.DEFAULT); } // public DlinkReceivePacket(HashMap jsonHash) { @@ -75,8 +80,8 @@ class DlinkReceivePacket extends DlinkPacket * @return the service that is being invoked */ Service getService() { - if (mService == null && mData != null) - mService = new Service(mData);//new String(Base64.decode(mData, Base64.DEFAULT))); +// if (mService == null && mData != null) +// mService = new Service(mData);//new String(Base64.decode(mData, Base64.DEFAULT))); return mService; } diff --git a/src/main/java/com/jaguarlandrover/rvi/Service.java b/src/main/java/com/jaguarlandrover/rvi/Service.java index 898fc14..2a49d7d 100644 --- a/src/main/java/com/jaguarlandrover/rvi/Service.java +++ b/src/main/java/com/jaguarlandrover/rvi/Service.java @@ -16,6 +16,7 @@ import android.util.Log; import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; import com.google.gson.internal.LinkedTreeMap; import java.util.ArrayList; @@ -29,18 +30,27 @@ class Service { private final static String TAG = "RVI:Service"; - private String mServiceIdentifier; + @SerializedName("service") + private String mJsonService = null; - private String mBundleIdentifier; + @SerializedName("parameters") + private Object mJsonParameters = null; - private String mDomain; + private String mServiceIdentifier = null; - private String mNodeIdentifier; + private String mBundleIdentifier = null; - private Object mParameters; + private String mDomain = null; + private String mNodeIdentifier = null; + + private Object mParameters = null; + + @SerializedName("timeout") private Long mTimeout; + Service() {} + /** * Instantiates a new Vehicle service. * @@ -54,6 +64,8 @@ class Service mBundleIdentifier = bundleIdentifier; mDomain = domain; mNodeIdentifier = prefix; + + mJsonService = getFullyQualifiedServiceName(); } HashMap unwrap(ArrayList parameters) { @@ -65,60 +77,40 @@ HashMap unwrap(ArrayList parameters) { return unwrapped; } - /** - * Instantiates a new Vehicle service. - * - * @param jsonString the json string - */ - Service(String jsonString) { - Log.d(TAG, "Service data: " + jsonString); - - Gson gson = new Gson(); - HashMap jsonHash = gson.fromJson(jsonString, HashMap.class); - String[] serviceParts = ((String) jsonHash.get("service")).split("/"); - - if (serviceParts.length != 5) return; - - mDomain = serviceParts[0]; - mNodeIdentifier = serviceParts[1] + "/" + serviceParts[2]; - mBundleIdentifier = serviceParts[3]; - mServiceIdentifier = serviceParts[4]; + /* If the Service object was deserialized from json, mParameters field might not yet have been unwrapped, but the mJsonParameters + field will be set. If this is the case, unwrap the mJsonParameters field into something more easily consumable and set mParameters. + We only have the intermediary value here, because RVI sends parameters as a _list_ of single-kvpair objects, instead of one + multi-kvpair object. This gives up the opportunity to unwrap the list into an object. */ + private Boolean shouldParseParameters() { + return mJsonParameters != null && mParameters == null; + } + private void parseParamters() { // TODO: Why are parameters arrays of object, not just an object? This should probably get fixed everywhere. - if (jsonHash.get("parameters").getClass().equals(ArrayList.class) && ((ArrayList)jsonHash.get("parameters")).size() == 1) - mParameters = ((ArrayList) jsonHash.get("parameters")).get(0); - else if (jsonHash.get("parameters").getClass().equals(ArrayList.class) && ((ArrayList)jsonHash.get("parameters")).size() > 1) - mParameters = unwrap((ArrayList) jsonHash.get("parameters")); + if (mJsonParameters.getClass().equals(ArrayList.class) && ((ArrayList)mJsonParameters).size() == 1) + mParameters = ((ArrayList) mJsonParameters).get(0); + else if (mJsonParameters.getClass().equals(ArrayList.class) && ((ArrayList)mJsonParameters).size() > 1) + mParameters = unwrap((ArrayList) mJsonParameters); else - mParameters = jsonHash.get("parameters"); + mParameters = mJsonParameters; } - /** - * Gets parameters. - * - * @return the parameters - */ - Object getParameters() { - return mParameters; + /* If the Service object was deserialized from json, some of its fields might not be set, but the mJsonService field will be set. + If this is the case, parse out the mJsonService field into its parts and set the rest of the fields. */ + private Boolean shouldParseServiceName() { + return mJsonService != null && (mDomain == null || mNodeIdentifier == null || mBundleIdentifier == null || mServiceIdentifier == null); } - /** - * Sets parameters. - * - * @param parameters the parameters - */ - void setParameters(Object parameters) { - this.mParameters = parameters; - } + private void parseFullyQualifiedServiceName() { + String[] serviceParts = mJsonService.split("/"); - /** - * Gets service identifier. - * - * @return the service identifier - */ - String getServiceIdentifier() { - return mServiceIdentifier; + if (serviceParts.length != 5) return; + + mDomain = serviceParts[0]; + mNodeIdentifier = serviceParts[1] + "/" + serviceParts[2]; + mBundleIdentifier = serviceParts[3]; + mServiceIdentifier = serviceParts[4]; } /** @@ -127,6 +119,9 @@ String getServiceIdentifier() { * @return the fully qualified service name */ String getFullyQualifiedServiceName() { + if (shouldParseServiceName()) + parseFullyQualifiedServiceName(); + return mDomain + "/" + mNodeIdentifier + "/" + mBundleIdentifier + "/" + mServiceIdentifier; } @@ -141,34 +136,25 @@ boolean hasNodeIdentifier() { } /** - * Generate request params. + * Sets the node identifier portion of the fully-qualified service name * - * @return the object + * @param nodeIdentifier the local or remote RVI node's identifier */ - Object generateRequestParams() { - HashMap params = new HashMap<>(4); - - params.put("service", getFullyQualifiedServiceName()); - params.put("parameters", mParameters);//Arrays.asList(mParameters)); - params.put("timeout", mTimeout); - params.put("tid", 1); // TODO: Please tell me we can not have this here - //params.put("signature", "signature"); - //params.put("certificate", "certificate"); - - return params; + void setNodeIdentifier(String nodeIdentifier) { + mNodeIdentifier = nodeIdentifier; + mJsonService = getFullyQualifiedServiceName(); } /** - * Json string. + * Gets the domain. * - * @return the string + * @return the domain */ - String jsonString() { - Gson gson = new Gson(); - - Log.d(TAG, "Service data: " + gson.toJson(generateRequestParams())); + String getDomain() { + if (shouldParseServiceName()) + parseFullyQualifiedServiceName(); - return gson.toJson(generateRequestParams()); + return mDomain; } /** @@ -177,25 +163,43 @@ String jsonString() { * @return the bundle identifier */ String getBundleIdentifier() { + if (shouldParseServiceName()) + parseFullyQualifiedServiceName(); + return mBundleIdentifier; } /** - * Gets the domain. + * Gets service identifier. * - * @return the domain + * @return the service identifier */ - String getDomain() { - return mDomain; + String getServiceIdentifier() { + if (shouldParseServiceName()) + parseFullyQualifiedServiceName(); + + return mServiceIdentifier; } /** - * Sets the node identifier portion of the fully-qualified service name + * Gets parameters. * - * @param nodeIdentifier the local or remote RVI node's identifier + * @return the parameters */ - void setNodeIdentifier(String nodeIdentifier) { - mNodeIdentifier = nodeIdentifier; + Object getParameters() { + if (shouldParseParameters()) + parseParamters(); + + return mParameters; + } + + /** + * Sets parameters. + * + * @param parameters the parameters + */ + void setParameters(Object parameters) { + this.mParameters = this.mJsonParameters = parameters; } /**