/*
 * Copyright (C) 2017 Square, Inc.
 *
 * 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.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Set;

public final class DefaultOnDataMismatchAdapter<T> extends JsonAdapter<T> {
  private final JsonAdapter<T> delegate;
  private final T defaultValue;
  private final JsonAdapter<Object> objectAdapter;

  private DefaultOnDataMismatchAdapter(JsonAdapter<T> delegate, T defaultValue,
      JsonAdapter<Object> objectAdapter) {
    this.delegate = delegate;
    this.defaultValue = defaultValue;
    this.objectAdapter = objectAdapter;
  }

  @Override public T fromJson(JsonReader reader) throws IOException {
    // Read the value first so that the reader will be in a known state even if there's an
    // exception. Otherwise it may be awkward to recover: it might be between calls to
    // beginObject() and endObject() for example.
    Object jsonValue = objectAdapter.fromJson(reader);

    // Use the delegate to convert the JSON value to the target type.
    try {
      return delegate.fromJsonValue(jsonValue);
    } catch (JsonDataException e) {
      return defaultValue;
    }
  }

  @Override public void toJson(JsonWriter writer, T value) throws IOException {
    delegate.toJson(writer, value);
  }

  public static <T> Factory newFactory(final Class<T> type, final T defaultValue) {
    return new Factory() {
      @Override public JsonAdapter<?> create(
          Type requestedType, Set<? extends Annotation> annotations, Moshi moshi) {
        if (type != requestedType) return null;
        JsonAdapter<Object> objectAdapter = moshi.adapter(Object.class);
        JsonAdapter<T> delegate = moshi.nextAdapter(this, type, annotations);
        return new DefaultOnDataMismatchAdapter<>(delegate, defaultValue, objectAdapter);
      }
    };
  }
}

@@ -1098,59 +1098,8 @@
 lue;
-%0A  private final JsonAdapter%3CObject%3E objectAdapter;
 %0A%0A  
@@ -1178,49 +1178,8 @@
 alue
-,%0A      JsonAdapter%3CObject%3E objectAdapter
 ) %7B%0A
@@ -1250,48 +1250,8 @@
 ue;%0A
-    this.objectAdapter = objectAdapter;%0A
   %7D%0A
@@ -1576,37 +1576,29 @@
 e = 
-objectAdapter.fromJson(reader
+reader.readJsonValue(
 );%0A%0A
@@ -2213,81 +2213,8 @@
 ll;%0A
-        JsonAdapter%3CObject%3E objectAdapter = moshi.adapter(Object.class);%0A
     
@@ -2363,23 +2363,8 @@
 alue
-, objectAdapter
 );%0A 

Use readJsonValue() in DefaultOnDataMismatchAdapter.