/* * Copyright (C) 2015 The Android Open Source Project * * 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 androidx.test.espresso.web.model; import static com.google.common.base.Preconditions.checkState; import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.NonNull; import com.google.common.base.Objects; import java.util.Map; import javax.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONStringer; import org.json.JSONTokener; /** Represents the results of a Javascript execution. */ public final class Evaluation implements JSONAble, Parcelable { private static final String STATUS_KEY = "status"; private static final String MESSAGE_KEY = "message"; private static final String VALUE_KEY = "value"; private int status; private boolean hasMessage; private String message; private Object value; private Evaluation(Builder b) { this.status = b.status; this.value = b.value; this.hasMessage = b.hasMessage; this.message = b.message; } protected Evaluation(Parcel in) { readFromParcel(in); } @Override public int hashCode() { return Objects.hashCode(status, value, hasMessage, message); } @Override public boolean equals(Object o) { if (o instanceof Evaluation) { Evaluation other = (Evaluation) o; if (other.status == status) { if (hasMessage == other.hasMessage) { if (hasMessage) { return message.equals(other.message); } else { if (value == null) { return other.value == null; } else { return value.equals(other.value); } } } } } return false; } public int getStatus() { return status; } @Nullable public Object getValue() { return value; } public boolean hasMessage() { return hasMessage; } public String getMessage() { checkState(hasMessage); return message; } @Override public String toJSONString() { try { JSONStringer stringer = new JSONStringer().object().key(STATUS_KEY).value(status).key(VALUE_KEY); if ((value instanceof String) || (value instanceof Number) || (value instanceof Boolean) || (value == null)) { stringer.value(value); } else { String jsonValue = ModelCodec.encode(value); stringer.value(new JSONTokener(jsonValue).nextValue()); } stringer.endObject(); return stringer.toString(); } catch (JSONException je) { throw new RuntimeException(je); } } static final JSONAble.DeJSONFactory DEJSONIZER = new JSONAble.DeJSONFactory() { @Override public Object attemptDeJSONize(Map<String, Object> map) { if (map.size() == 2) { Object maybeStatus = map.get(STATUS_KEY); if (maybeStatus instanceof Integer) { Object maybeValue = map.get(VALUE_KEY); if (null != maybeValue) { Evaluation.Builder builder = new Evaluation.Builder() .setStatus((Integer) maybeStatus) .setValue(maybeValue == JSONObject.NULL ? null : maybeValue); if (maybeValue instanceof Map) { Map mapValue = (Map) maybeValue; if (mapValue.size() == 1) { Object maybeMessage = mapValue.get(MESSAGE_KEY); if (maybeMessage instanceof String) { builder.setMessage((String) maybeMessage); } else if (maybeMessage == JSONObject.NULL) { builder.setMessage(null); } } } return builder.build(); } } } return null; } }; @Override public String toString() { return String.format( "Evaluation: status: %d value: %s hasMessage: %s message: %s", status, value, hasMessage, message); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(ModelCodec.encode(this)); } public void readFromParcel(Parcel in) { Evaluation evaluation = ModelCodec.decodeEvaluation(in.readString()); status = evaluation.status; hasMessage = evaluation.hasMessage; message = evaluation.message; value = evaluation.value; } public static final Creator<Evaluation> CREATOR = new Parcelable.Creator<Evaluation>() { @Override public Evaluation createFromParcel(Parcel in) { return new Evaluation(in); } @Override public Evaluation[] newArray(int size) { return new Evaluation[size]; } }; static class Builder { private Object value; private int status; private boolean hasMessage; private String message; public Builder setMessage(String message) { this.message = message; hasMessage = true; return this; } public Builder setValue(Object value) { this.value = value; return this; } public Builder setStatus(int status) { this.status = status; return this; } public Evaluation build() { return new Evaluation(this); } } }