/*
* Copyright (C) 2014 SCVNGR, Inc. d/b/a LevelUp
*
* 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.scvngr.levelup.core.model.util;
import android.annotation.SuppressLint;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import net.jcip.annotations.Immutable;
import java.util.ArrayList;
import java.util.Collection;
/**
* An ArrayList which is also Parcelable. Subclasses must implement part of the Parcelable
* interface: add a static CREATOR which implements {@link android.os.Parcelable.Creator}.
*
* @param <E> the type of object this array holds.
*/
@SuppressLint("ParcelCreator")
@Immutable
public abstract class ParcelableArrayList<E extends Parcelable> extends ArrayList<E> implements
Parcelable {
/**
* Serializable ID.
*/
private static final long serialVersionUID = -1446873132782056704L;
/**
* True when the array is being loaded from the constructor. This is needed, as
* {@link Parcel#readTypedList(java.util.List, android.os.Parcelable.Creator)} uses the
* {@link #add(Parcelable)} methods to populate the array and otherwise this class must be
* immutable.
*/
private Boolean mIsBeingReadFromParcel = false;
/**
* Creates a new ArrayList, copying from the source collection.
*
* @param source the source collection to copy from.
*/
/*
* It is intentional that this isn't Collection<? extends E> like the superclass's constructor,
* as readTypedList requires a homogeneous list.
*/
public ParcelableArrayList(final Collection<E> source) {
super(source);
}
/**
* @param in the parcel to read from.
*/
public ParcelableArrayList(@NonNull final Parcel in) {
synchronized (mIsBeingReadFromParcel) {
mIsBeingReadFromParcel = true;
in.readTypedList(this, getCreator());
mIsBeingReadFromParcel = false;
}
}
@Override
public final boolean add(final E object) {
synchronized (mIsBeingReadFromParcel) {
boolean result;
if (mIsBeingReadFromParcel) {
result = super.add(object);
} else {
throw new ImmutableClassException();
}
return result;
}
}
@Override
public final void add(final int index, final E object) {
synchronized (mIsBeingReadFromParcel) {
if (mIsBeingReadFromParcel) {
super.add(index, object);
} else {
throw new ImmutableClassException();
}
}
}
@Override
public final boolean addAll(final Collection<? extends E> collection) {
synchronized (mIsBeingReadFromParcel) {
boolean result;
if (mIsBeingReadFromParcel) {
result = super.addAll(collection);
} else {
throw new ImmutableClassException();
}
return result;
}
}
@Override
public final boolean
addAll(final int index, final java.util.Collection<? extends E> collection) {
synchronized (mIsBeingReadFromParcel) {
boolean result;
if (mIsBeingReadFromParcel) {
result = super.addAll(index, collection);
} else {
throw new ImmutableClassException();
}
return result;
}
}
@Override
public final void clear() {
throw new ImmutableClassException();
}
@Override
public int describeContents() {
return 0;
}
@Override
public final void ensureCapacity(final int minimumCapacity) {
throw new ImmutableClassException();
}
@Override
public final E remove(final int index) {
throw new ImmutableClassException();
}
@Override
public final boolean remove(final Object object) {
throw new ImmutableClassException();
}
@Override
public final boolean removeAll(final Collection<?> collection) {
throw new ImmutableClassException();
}
@Override
public final boolean retainAll(final Collection<?> collection) {
throw new ImmutableClassException();
}
@Override
public final E set(final int index, final E object) {
throw new ImmutableClassException();
}
@Override
public final void trimToSize() {
throw new ImmutableClassException();
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeTypedList(this);
}
/**
* Subclasses must implement this, returning the CREATOR of the array's Parcelable item.
*
* @return the Parcelable item's creator.
*/
@NonNull
protected abstract Creator<E> getCreator();
@Override
protected final void removeRange(final int fromIndex, final int toIndex) {
throw new ImmutableClassException();
}
/**
* This class is immutable.
*/
public static final class ImmutableClassException extends UnsupportedOperationException {
/**
* Serializable ID.
*/
private static final long serialVersionUID = 7301994074859654557L;
/**
* Default message.
*/
public ImmutableClassException() {
super("This class is immutable, operation not permitted.");
}
}
}