paperparcel.AdapterRegistry.java Source code

Java tutorial

Introduction

Here is the source code for paperparcel.AdapterRegistry.java

Source

/*
 * Copyright (C) 2016 Bradley Campbell.
 *
 * 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 paperparcel;

import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.squareup.javapoet.TypeName;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import paperparcel.TypeKey.*;

/**
 * Responsible for caching the qualified class names of all of the TypeAdapters discovered across
 * the various processing rounds and also cache {@link AdapterDescriptor} instances as these can be
 * expensive to create.
 */
final class AdapterRegistry {
    private static final TypeKey STRING = ClassKey.get("java.lang.String");
    private static final TypeKey INTEGER = ClassKey.get("java.lang.Integer");
    private static final TypeKey MAP = ParameterizedKey.get(ClassKey.get("java.util.Map"),
            asList(AnyKey.get("K"), AnyKey.get("V")));
    private static final TypeKey BUNDLE = ClassKey.get("android.os.Bundle");
    private static final TypeKey PERSISTABLE_BUNDLE = ClassKey.get("android.os.PersistableBundle");
    private static final TypeKey PARCELABLE = BoundedKey.get("T", asList(ClassKey.get("android.os.Parcelable")));
    private static final TypeKey SHORT = ClassKey.get("java.lang.Short");
    private static final TypeKey LONG = ClassKey.get("java.lang.Long");
    private static final TypeKey FLOAT = ClassKey.get("java.lang.Float");
    private static final TypeKey DOUBLE = ClassKey.get("java.lang.Double");
    private static final TypeKey BOOLEAN = ClassKey.get("java.lang.Boolean");
    private static final TypeKey CHAR_SEQUENCE = ClassKey.get("java.lang.CharSequence");
    private static final TypeKey LIST = ParameterizedKey.get(ClassKey.get("java.util.List"),
            asList(AnyKey.get("T")));
    private static final TypeKey SPARSE_ARRAY = ParameterizedKey.get(ClassKey.get("android.util.SparseArray"),
            asList(AnyKey.get("T")));
    private static final TypeKey BOOLEAN_ARRAY = PrimitiveArrayKey.BOOLEAN_ARRAY;
    private static final TypeKey BYTE_ARRAY = PrimitiveArrayKey.BYTE_ARRAY;
    private static final TypeKey IBINDER = ClassKey.get("android.os.IBinder");
    private static final TypeKey INT_ARRAY = PrimitiveArrayKey.INT_ARRAY;
    private static final TypeKey LONG_ARRAY = PrimitiveArrayKey.LONG_ARRAY;
    private static final TypeKey BYTE = ClassKey.get("java.lang.Byte");
    private static final TypeKey SIZE = ClassKey.get("android.util.Size");
    private static final TypeKey SIZE_F = ClassKey.get("android.util.SizeF");
    private static final TypeKey DOUBLE_ARRAY = PrimitiveArrayKey.DOUBLE_ARRAY;
    private static final TypeKey SPARSE_BOOLEAN_ARRAY = ClassKey.get("android.util.SparseBooleanArray");
    private static final TypeKey COLLECTION = ParameterizedKey.get(ClassKey.get("java.util.Collection"),
            asList(AnyKey.get("T")));
    private static final TypeKey OBJECT_ARRAY = ArrayKey.of(AnyKey.get("T"));
    private static final TypeKey SET = ParameterizedKey.get(ClassKey.get("java.util.Set"), asList(AnyKey.get("T")));
    private static final TypeKey CHAR_ARRAY = PrimitiveArrayKey.CHAR_ARRAY;
    private static final TypeKey FLOAT_ARRAY = PrimitiveArrayKey.FLOAT_ARRAY;
    private static final TypeKey SHORT_ARRAY = PrimitiveArrayKey.SHORT_ARRAY;
    private static final TypeKey CHARACTER = ClassKey.get("java.lang.Character");
    private static final TypeKey ENUM = BoundedKey.get("T",
            asList(ParameterizedKey.get(ClassKey.get("java.lang.Enum"), asList(AnyKey.get("T")))));
    private static final TypeKey SERIALIZABLE = BoundedKey.get("T", asList(ClassKey.get("java.io.Serializable")));

    private static final String STATIC_ADAPTERS = "paperparcel.internal.StaticAdapters";

    private static ImmutableList<TypeKey> asList(TypeKey... keys) {
        ImmutableList.Builder<TypeKey> builder = ImmutableList.builder();
        for (TypeKey key : keys) {
            builder.add(key);
        }
        return builder.build();
    }

    static abstract class Entry {
        abstract TypeKey typeKey();

        abstract boolean nullSafe();
    }

    @AutoValue
    static abstract class ClassEntry extends Entry {
        abstract String qualifiedName();

        static ClassEntry create(String qualifiedName, TypeKey key, boolean nullSafe) {
            return new AutoValue_AdapterRegistry_ClassEntry(key, nullSafe, qualifiedName);
        }
    }

    @AutoValue
    static abstract class FieldEntry extends Entry {
        abstract String enclosingClass();

        abstract String fieldName();

        static FieldEntry create(String enclosingClass, String fieldName, TypeKey key, boolean nullSafe) {
            return new AutoValue_AdapterRegistry_FieldEntry(key, nullSafe, enclosingClass, fieldName);
        }
    }

    private static final ImmutableList<Entry> BUILT_IN_ADAPTER_ENTRIES = ImmutableList.of(
            FieldEntry.create(STATIC_ADAPTERS, "STRING_ADAPTER", STRING, true),
            FieldEntry.create(STATIC_ADAPTERS, "INTEGER_ADAPTER", INTEGER, false),
            ClassEntry.create("paperparcel.internal.MapAdapter", MAP, false),
            FieldEntry.create(STATIC_ADAPTERS, "BUNDLE_ADAPTER", BUNDLE, true),
            FieldEntry.create(STATIC_ADAPTERS, "PERSISTABLE_BUNDLE_ADAPTER", PERSISTABLE_BUNDLE, true),
            ClassEntry.create("paperparcel.internal.ParcelableAdapter", PARCELABLE, true),
            FieldEntry.create(STATIC_ADAPTERS, "SHORT_ADAPTER", SHORT, false),
            FieldEntry.create(STATIC_ADAPTERS, "LONG_ADAPTER", LONG, false),
            FieldEntry.create(STATIC_ADAPTERS, "FLOAT_ADAPTER", FLOAT, false),
            FieldEntry.create(STATIC_ADAPTERS, "DOUBLE_ADAPTER", DOUBLE, false),
            FieldEntry.create(STATIC_ADAPTERS, "BOOLEAN_ADAPTER", BOOLEAN, false),
            FieldEntry.create(STATIC_ADAPTERS, "CHAR_SEQUENCE_ADAPTER", CHAR_SEQUENCE, true),
            ClassEntry.create("paperparcel.internal.ListAdapter", LIST, false),
            ClassEntry.create("paperparcel.internal.SparseArrayAdapter", SPARSE_ARRAY, false),
            FieldEntry.create(STATIC_ADAPTERS, "BOOLEAN_ARRAY_ADAPTER", BOOLEAN_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "BYTE_ARRAY_ADAPTER", BYTE_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "IBINDER_ADAPTER", IBINDER, true),
            FieldEntry.create(STATIC_ADAPTERS, "INT_ARRAY_ADAPTER", INT_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "LONG_ARRAY_ADAPTER", LONG_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "BYTE_ADAPTER", BYTE, false),
            FieldEntry.create(STATIC_ADAPTERS, "SIZE_ADAPTER", SIZE, false),
            FieldEntry.create(STATIC_ADAPTERS, "SIZE_F_ADAPTER", SIZE_F, false),
            FieldEntry.create(STATIC_ADAPTERS, "DOUBLE_ARRAY_ADAPTER", DOUBLE_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "SPARSE_BOOLEAN_ARRAY_ADAPTER", SPARSE_BOOLEAN_ARRAY, true),
            ClassEntry.create("paperparcel.internal.CollectionAdapter", COLLECTION, false),
            ClassEntry.create("paperparcel.internal.SetAdapter", SET, false),
            FieldEntry.create(STATIC_ADAPTERS, "CHAR_ARRAY_ADAPTER", CHAR_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "FLOAT_ARRAY_ADAPTER", FLOAT_ARRAY, true),
            FieldEntry.create(STATIC_ADAPTERS, "SHORT_ARRAY_ADAPTER", SHORT_ARRAY, false),
            FieldEntry.create(STATIC_ADAPTERS, "CHARACTER_ADAPTER", CHARACTER, false),
            ClassEntry.create("paperparcel.internal.EnumAdapter", ENUM, false),
            ClassEntry.create("paperparcel.internal.ArrayAdapter", OBJECT_ARRAY, false),
            // Serializable must be last.
            ClassEntry.create("paperparcel.internal.SerializableAdapter", SERIALIZABLE, false));

    private final List<Entry> entries = Lists.newArrayList(BUILT_IN_ADAPTER_ENTRIES);
    private final Map<TypeName, AdapterDescriptor> adapters = Maps.newLinkedHashMap();

    private final Elements elements;
    private final Types types;

    AdapterRegistry(Elements elements, Types types) {
        this.elements = elements;
        this.types = types;
    }

    void addClassEntry(TypeElement element, boolean nullSafe) {
        String qualifiedName = element.getQualifiedName().toString();
        TypeKey key = TypeKey.get(Utils.getAdaptedType(elements, types, MoreTypes.asDeclared(element.asType())));
        Entry entry = ClassEntry.create(qualifiedName, key, nullSafe);
        entries.add(0, entry);
    }

    boolean contains(TypeElement element) {
        for (Entry entry : entries) {
            if (entry instanceof ClassEntry) {
                if (element.getQualifiedName().contentEquals(((ClassEntry) entry).qualifiedName())) {
                    return true;
                }
            }
        }
        return false;
    }

    List<Entry> getEntries(boolean allowSerializable) {
        if (allowSerializable) {
            return entries;
        } else {
            return entries.subList(0, entries.size() - 1);
        }
    }

    void registerAdapterFor(TypeName fieldType, AdapterDescriptor adapter) {
        adapters.put(fieldType, adapter);
    }

    Optional<AdapterDescriptor> getAdapterFor(TypeName fieldType) {
        return Optional.fromNullable(adapters.get(fieldType));
    }
}