/*
 * Copyright 2016 requery.io
 *
 * 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 io.requery.android;

import android.os.Parcel;
import io.requery.meta.Attribute;
import io.requery.meta.Type;
import io.requery.proxy.EntityProxy;
import io.requery.proxy.PropertyState;

/**
 * Handler for Android's Parcelable objects. Serializes field types that are handled by
 * {@link Parcel#readValue(ClassLoader)} and {@link Parcel#writeValue(Object)}. If using a field
 * that doesn't support those you must implement the parcelable interface in the object.
 *
 * @author Nikhil Purushe
 */
public class EntityParceler<T> {

    private final Type<T> type;

    public EntityParceler(Type<T> type) {
        this.type = type;
    }

    public T readFromParcel(Parcel in) {
        T entity = type.getFactory().get();
        EntityProxy<T> proxy = type.getProxyProvider().apply(entity);
        for (Attribute<T, ?> attribute : type.getAttributes()) {
            if (attribute.isAssociation()) {
                continue;
            }
            Class<?> typeClass = attribute.getClassType();
            Object value;
            if (typeClass.isEnum()) {
                String name = (String) in.readValue(getClass().getClassLoader());
                if (name == null) {
                    value = null;
                } else {
                    @SuppressWarnings("unchecked")
                    Class<? extends Enum> enumClass = (Class<? extends Enum>) typeClass;
                    value = Enum.valueOf(enumClass, name);
                }
            } else {
                value = in.readValue(getClass().getClassLoader());
            }
            PropertyState state = PropertyState.LOADED;
            if (!type.isStateless()) {
                state = PropertyState.valueOf(in.readString());
            }
            proxy.setObject(attribute, value, state);
        }
        return entity;
    }

    public void writeToParcel(T entity, Parcel out) {
        EntityProxy<T> proxy = type.getProxyProvider().apply(entity);
        for (Attribute<T, ?> attribute : type.getAttributes()) {
            if (attribute.isAssociation()) {
                continue;
            }
            Object value = proxy.get(attribute, false);
            Class<?> typeClass = attribute.getClassType();
            if (typeClass.isEnum()) {
                if (value != null) {
                    value = value.toString();
                }
            }
            out.writeValue(value);
            if (!type.isStateless()) {
                PropertyState state = proxy.getState(attribute);
                out.writeString(state.toString());
            }
        }
    }
}

@@ -643,16 +643,46 @@
 Parcel;%0A
+import android.os.Parcelable;%0A
 import i
@@ -1654,16 +1654,23 @@
 ct value
+ = null
 ;%0A      
@@ -2087,32 +2087,636 @@
               %7D%0A
+            %7D else if (typeClass.isArray()) %7B%0A                int length = in.readInt();%0A                if (length %3E= 0) %7B%0A                    try %7B%0A                        Parcelable.Creator creator = (Parcelable.Creator%3C?%3E)%0A                                typeClass.getField(%22CREATOR%22).get(null);%0A                        Object%5B%5D array = creator.newArray(length);%0A                        in.readTypedArray(array, creator);%0A                        value = array;%0A                    %7D catch (Exception e) %7B%0A                        throw new RuntimeException(e);%0A                    %7D%0A                %7D%0A
             %7D el
@@ -3449,32 +3449,372 @@
 getClassType();%0A
+            if (typeClass.isArray()) %7B%0A                Parcelable%5B%5D array = (Parcelable%5B%5D) value;%0A                if (array == null) %7B%0A                    out.writeInt(-1);%0A                %7D else %7B%0A                    out.writeInt(array.length);%0A                    out.writeTypedArray(array, 0);%0A                %7D%0A            %7D else %7B%0A    
             if (
@@ -3847,24 +3847,28 @@
             
+    
 if (value !=
@@ -3868,32 +3868,36 @@
 alue != null) %7B%0A
+    
                 
@@ -3934,34 +3934,42 @@
                 
+   
+ 
 %7D%0A
+    
             %7D%0A  
@@ -3958,32 +3958,36 @@
               %7D%0A
+    
             out.
@@ -4001,24 +4001,38 @@
 lue(value);%0A
+            %7D%0A
             

Resolve #285 Support arrays in EntityParceler