Skip to content

Commit

Permalink
Remove toJson() from StripeJsonModel
Browse files Browse the repository at this point in the history
`toJson()` was previously used in the implementation of `equals()`
(see #813). Now that it is no longer used in `equals()`, it is
no longer needed.

Remove all implementations of toJson() and rename StripeJsonModel
to StripeModel.

Also improve object construction in `AbstractEphemeralKey` by
creating a Builder object instead of using reflection.
  • Loading branch information
mshafrir-stripe committed Jun 10, 2019
1 parent 54c9538 commit 3abcad6
Show file tree
Hide file tree
Showing 58 changed files with 686 additions and 1,664 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ private void retrievePaymentIntent() {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
paymentIntent -> mPaymentIntentValue.setText(paymentIntent != null ?
paymentIntent.toJson().toString() :
new JSONObject(paymentIntent.toMap()).toString() :
getString(R.string.error_while_retrieving_payment_intent)),
throwable -> Log.e(TAG, throwable.toString())
);
Expand Down Expand Up @@ -188,7 +188,8 @@ private void confirmPaymentIntent(@NonNull final Card card) {
.subscribe(
paymentIntent -> {
if (paymentIntent != null) {
mPaymentIntentValue.setText(paymentIntent.toJson().toString());
mPaymentIntentValue.setText(
new JSONObject(paymentIntent.toMap()).toString());

if (paymentIntent.requiresAction()) {
Toast.makeText(PaymentIntentActivity.this,
Expand Down
218 changes: 102 additions & 116 deletions stripe/src/main/java/com/stripe/android/AbstractEphemeralKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,23 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.stripe.android.model.StripeJsonModel;
import com.stripe.android.model.StripeModel;
import com.stripe.android.utils.ObjectUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.InvocationTargetException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
* Represents an Ephemeral Key that can be used temporarily for certain operations.
*/
abstract class AbstractEphemeralKey extends StripeJsonModel implements Parcelable {
abstract class AbstractEphemeralKey extends StripeModel implements Parcelable {

static final String FIELD_CREATED = "created";
static final String FIELD_EXPIRES = "expires";
Expand All @@ -32,7 +31,6 @@ abstract class AbstractEphemeralKey extends StripeJsonModel implements Parcelabl
static final String FIELD_ID = "id";
static final String FIELD_ASSOCIATED_OBJECTS = "associated_objects";
static final String FIELD_TYPE = "type";
static final String NULL = "null";

@NonNull final String mObjectId;
private final long mCreated;
Expand All @@ -53,83 +51,30 @@ abstract class AbstractEphemeralKey extends StripeJsonModel implements Parcelabl
*/
AbstractEphemeralKey(@NonNull Parcel in) {
mCreated = in.readLong();
mObjectId = in.readString();
mObjectId = Objects.requireNonNull(in.readString());
mExpires = in.readLong();
mId = in.readString();
mId = Objects.requireNonNull(in.readString());
mLiveMode = in.readInt() == 1;
mObject = in.readString();
mSecret = in.readString();
mType = in.readString();
mObject = Objects.requireNonNull(in.readString());
mSecret = Objects.requireNonNull(in.readString());
mType = Objects.requireNonNull(in.readString());
}

AbstractEphemeralKey(
long created,
@NonNull String objectId,
long expires,
@NonNull String id,
boolean liveMode,
@NonNull String object,
@NonNull String secret,
@NonNull String type
) {
mCreated = created;
mObjectId = objectId;
mExpires = expires;
mId = id;
mLiveMode = liveMode;
mObject = object;
mSecret = secret;
mType = type;
}

AbstractEphemeralKey(@Nullable JSONObject jsonObject) throws JSONException {
mCreated = jsonObject.getLong(FIELD_CREATED);
mExpires = jsonObject.getLong(FIELD_EXPIRES);
mId = jsonObject.getString(FIELD_ID);
mLiveMode = jsonObject.getBoolean(FIELD_LIVEMODE);
mObject = jsonObject.getString(FIELD_OBJECT);
mSecret = jsonObject.getString(FIELD_SECRET);

// Get the values from the associated objects array first element
JSONArray associatedObjectArray = jsonObject.getJSONArray(FIELD_ASSOCIATED_OBJECTS);
JSONObject typeObject = associatedObjectArray.getJSONObject(0);
mType = typeObject.getString(FIELD_TYPE);
mObjectId = typeObject.getString(FIELD_ID);
}

@NonNull
@Override
public JSONObject toJson() {
JSONObject jsonObject = new JSONObject();
JSONArray associatedObjectsArray = new JSONArray();
JSONObject associatedObject = new JSONObject();

try {
jsonObject.put(FIELD_CREATED, mCreated);
jsonObject.put(FIELD_EXPIRES, mExpires);
jsonObject.put(FIELD_OBJECT, mObject);
jsonObject.put(FIELD_ID, mId);
jsonObject.put(FIELD_SECRET, mSecret);
jsonObject.put(FIELD_LIVEMODE, mLiveMode);

associatedObject.put(FIELD_TYPE, mType);
associatedObject.put(FIELD_ID, mObjectId);
associatedObjectsArray.put(associatedObject);

jsonObject.put(FIELD_ASSOCIATED_OBJECTS, associatedObjectsArray);
} catch (JSONException impossible) {
// An exception can only be thrown from put operations if the key is null
// or the value is a non-finite number.
throw new IllegalArgumentException("JSONObject creation exception thrown.");
}

return jsonObject;
AbstractEphemeralKey(@NonNull Builder builder) {
mCreated = builder.mCreated;
mObjectId = Objects.requireNonNull(builder.mObjectId);
mExpires = builder.mExpires;
mId = Objects.requireNonNull(builder.mId);
mLiveMode = builder.mLiveMode;
mObject = Objects.requireNonNull(builder.mObject);
mSecret = Objects.requireNonNull(builder.mSecret);
mType = Objects.requireNonNull(builder.mType);
}

@NonNull
@Override
public Map<String, Object> toMap() {
final AbstractMap<String, Object> map = new HashMap<>();
final Map<String, Object> map = new HashMap<>();
map.put(FIELD_CREATED, mCreated);
map.put(FIELD_EXPIRES, mExpires);
map.put(FIELD_OBJECT, mObject);
Expand Down Expand Up @@ -161,12 +106,11 @@ public int describeContents() {
* @param flags any flags (unused) for writing this object
*/
@Override
public void writeToParcel(Parcel out, int flags) {
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeLong(mCreated);
out.writeString(mObjectId);
out.writeLong(mExpires);
out.writeString(mId);
// There is no writeBoolean
out.writeInt(mLiveMode ? 1 : 0);
out.writeString(mObject);
out.writeString(mSecret);
Expand Down Expand Up @@ -205,49 +149,24 @@ String getType() {
return mType;
}

@NonNull
protected static <TEphemeralKey extends AbstractEphemeralKey> TEphemeralKey fromString(
@Nullable String rawJson, Class ephemeralKeyClass) throws JSONException {
if (rawJson == null) {
throw new IllegalArgumentException("Attempted to instantiate " +
ephemeralKeyClass.getSimpleName() + " with null raw key");
}
JSONObject object = new JSONObject(rawJson);
return fromJson(object, ephemeralKeyClass);
}

@NonNull
protected static <TEphemeralKey extends AbstractEphemeralKey> TEphemeralKey fromJson(
@Nullable JSONObject jsonObject, Class ephemeralKeyClass) {
if (jsonObject == null) {
throw new IllegalArgumentException("Exception instantiating " +
ephemeralKeyClass.getSimpleName() +
" null JSON");
}

try {
return (TEphemeralKey)
ephemeralKeyClass.getConstructor(JSONObject.class).newInstance(jsonObject);
} catch (InstantiationException e) {
throw new IllegalArgumentException("Exception instantiating " +
ephemeralKeyClass.getSimpleName(), e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Exception instantiating " +
ephemeralKeyClass.getSimpleName(), e);
} catch (InvocationTargetException e) {
if (e.getTargetException() != null) {
throw new IllegalArgumentException("Improperly formatted JSON for ephemeral key " +
ephemeralKeyClass.getSimpleName() +
" - " + e.getTargetException().getMessage(),
e.getTargetException());
}
throw new IllegalArgumentException("Improperly formatted JSON for ephemeral key " +
ephemeralKeyClass.getSimpleName(), e);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Class " +
ephemeralKeyClass.getSimpleName() +
" does not have an accessible (JSONObject) constructor", e);
}
@NonNull JSONObject jsonObject, @NonNull Builder<TEphemeralKey> builder)
throws JSONException {
// Get the values from the associated objects array first element
final JSONArray associatedObjectArray = jsonObject.getJSONArray(FIELD_ASSOCIATED_OBJECTS);
final JSONObject typeObject = associatedObjectArray.getJSONObject(0);

return builder
.setCreated(jsonObject.getLong(FIELD_CREATED))
.setExpires(jsonObject.getLong(FIELD_EXPIRES))
.setId(jsonObject.getString(FIELD_ID))
.setLiveMode(jsonObject.getBoolean(FIELD_LIVEMODE))
.setObject(jsonObject.getString(FIELD_OBJECT))
.setSecret(jsonObject.getString(FIELD_SECRET))
.setType(typeObject.getString(FIELD_TYPE))
.setObjectId(typeObject.getString(FIELD_ID))
.build();
}

@Override
Expand All @@ -272,4 +191,71 @@ public int hashCode() {
return ObjectUtils.hash(mObjectId, mCreated, mExpires, mId, mLiveMode, mObject, mSecret,
mType);
}

abstract static class Builder<T extends AbstractEphemeralKey> {
@Nullable private String mObjectId;
private long mCreated;
private long mExpires;
@Nullable private String mId;
private boolean mLiveMode;
@Nullable private String mObject;
@Nullable private String mSecret;
@Nullable private String mType;

@NonNull
Builder<T> setObjectId(@NonNull String objectId) {
this.mObjectId = objectId;
return this;
}

@NonNull
Builder<T> setCreated(long created) {
this.mCreated = created;
return this;
}

@NonNull
Builder<T> setExpires(long expires) {
this.mExpires = expires;
return this;
}

@NonNull
Builder<T> setId(@NonNull String id) {
this.mId = id;
return this;
}

@NonNull
Builder<T> setLiveMode(boolean liveMode) {
this.mLiveMode = liveMode;
return this;
}

@NonNull
Builder<T> setObject(@NonNull String object) {
this.mObject = object;
return this;
}

@NonNull
Builder<T> setSecret(@NonNull String secret) {
this.mSecret = secret;
return this;
}

@NonNull
Builder<T> setType(@NonNull String type) {
this.mType = type;
return this;
}

@NonNull
abstract T build();
}

abstract static class BuilderFactory<Builder extends AbstractEphemeralKey.Builder<?>> {
@NonNull
abstract Builder create();
}
}
53 changes: 20 additions & 33 deletions stripe/src/main/java/com/stripe/android/CustomerEphemeralKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import org.json.JSONException;
import org.json.JSONObject;

class CustomerEphemeralKey extends AbstractEphemeralKey {
final class CustomerEphemeralKey extends AbstractEphemeralKey {
public static final Parcelable.Creator<CustomerEphemeralKey> CREATOR
= new Parcelable.Creator<CustomerEphemeralKey>() {

Expand All @@ -27,30 +26,8 @@ private CustomerEphemeralKey(@NonNull Parcel in) {
super(in);
}

protected CustomerEphemeralKey(
long created,
@NonNull String customerId,
long expires,
@NonNull String id,
boolean liveMode,
@NonNull String object,
@NonNull String secret,
@NonNull String type
) {
super(created,
customerId,
expires,
id,
liveMode,
object,
secret,
type);

}

@SuppressWarnings("checkstyle:RedundantModifier") // Not actually redundant :|
public CustomerEphemeralKey(@Nullable JSONObject jsonObject) throws JSONException {
super(jsonObject);
private CustomerEphemeralKey(@NonNull Builder builder) {
super(builder);
}

@NonNull
Expand All @@ -59,14 +36,24 @@ String getCustomerId() {
}

@NonNull
static CustomerEphemeralKey fromString(@Nullable String rawJson) throws JSONException {
return AbstractEphemeralKey
.fromString(rawJson, CustomerEphemeralKey.class);
static CustomerEphemeralKey fromJson(@NonNull JSONObject jsonObject) throws JSONException {
return AbstractEphemeralKey.fromJson(jsonObject, new Builder());
}

@NonNull
static CustomerEphemeralKey fromJson(@Nullable JSONObject jsonObject) {
return AbstractEphemeralKey
.fromJson(jsonObject, CustomerEphemeralKey.class);
static final class Builder extends AbstractEphemeralKey.Builder<CustomerEphemeralKey> {
@NonNull
@Override
CustomerEphemeralKey build() {
return new CustomerEphemeralKey(this);
}
}

static final class BuilderFactory extends AbstractEphemeralKey
.BuilderFactory<AbstractEphemeralKey.Builder<CustomerEphemeralKey>> {
@NonNull
@Override
Builder create() {
return new Builder();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public void onError(@NonNull StripeException exception, @NonNull String operatio
KEY_REFRESH_BUFFER_IN_SECONDS,
proxyNowCalendar,
mOperationIdFactory,
CustomerEphemeralKey.class);
new CustomerEphemeralKey.BuilderFactory());
}

@RestrictTo(RestrictTo.Scope.LIBRARY)
Expand Down
Loading

0 comments on commit 3abcad6

Please sign in to comment.