/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.stetho.inspector.elements;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListView;
import com.facebook.stetho.common.Accumulator;
/**
* This interface marks a {@link Descriptor} in a way that is specially understood by
* {@link DescriptorMap}. When registered for a particular class 'E', a {@link Descriptor} that
* implements this interface will be chained (via {@link ChainedDescriptor#setSuper(Descriptor)}) to
* the {@link Descriptor} that is registered for the super class of E. If the super class of E
* doesn't have a registration, then the super-super class will be used (and so on). This allows you
* to implement {@link Descriptor} for any class in an inheritance hierarchy without having to
* couple it (via direct inheritance) to the super-class' {@link Descriptor}.<p/>
*
* To understand why this is useful, let's say you wanted to write a {@link Descriptor} for
* {@link ListView}. You have three options:<p/>
*
* The first option is to derive directly from {@link Descriptor} and write code to describe
* everything about instances of {@link ListView}, including details that are exposed by super
* classes such as {@link ViewGroup}, {@link View}, and even {@link Object}. This isn't generally
* a very good choice because it would require a lot of duplicated code amongst many descriptor
* implementations.<p/>
*
* The second option is to derive your 'ListViewDescriptor' from
* {@link com.facebook.stetho.inspector.elements.android.ViewGroupDescriptor} and only implement
* code to describe how {@link ListView} differs from {@link ViewGroup}. This will result in a class
* hierarchy that is parallel to the one that you are describing, but is also not a good choice for
* two reasons (let's assume for the moment that
* {@link com.facebook.stetho.inspector.elements.android.ViewGroupDescriptor} is deriving from
* {@link com.facebook.stetho.inspector.elements.android.ViewDescriptor}). The first problem is that
* you will need to write code for aggregating results from the super-class in methods such as
* {@link Descriptor#getChildren(Object, Accumulator)} and
* {@link Descriptor#getAttributes(Object, AttributeAccumulator)}. The second problem is that you'd
* end up with a log of fragility if you ever want to implement a descriptor for classes that are
* in-between {@link ViewGroup} and {@link ListView}, e.g. {@link AbsListView}. Any descriptor that
* derived from {@link com.facebook.stetho.inspector.elements.android.ViewGroupDescriptor} and
* described a class deriving from {@link AbsListView} would have to be modified to now derive from
* 'AbsListViewDescriptor'.<p/>
*
* The third option is to implement {@link ChainedDescriptor} (e.g. by deriving from
* {@link AbstractChainedDescriptor}) which solves all of these issues for you.<p/>
*/
public interface ChainedDescriptor<E> {
void setSuper(Descriptor<? super E> superDescriptor);
}