<commit_before>/*
 * Copyright 2014-present Facebook, 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.facebook.litho.sections;

import android.support.annotation.Nullable;
import com.facebook.litho.ComponentsPools;
import com.facebook.litho.Diff;
import com.facebook.litho.EventDispatcher;
import com.facebook.litho.EventHandler;
import com.facebook.litho.EventTrigger;
import com.facebook.litho.EventTriggerTarget;
import com.facebook.litho.Output;
import com.facebook.litho.TreeProps;
import com.facebook.litho.annotations.OnCreateTreeProp;
import com.facebook.litho.sections.annotations.DiffSectionSpec;
import com.facebook.litho.sections.annotations.GroupSectionSpec;
import com.facebook.litho.sections.annotations.OnDataBound;
import com.facebook.litho.sections.annotations.OnDiff;

public abstract class SectionLifecycle implements EventDispatcher, EventTriggerTarget {

  protected interface StateContainer {}

  /**
   * This methods will delegate to the {@link GroupSectionSpec}
   * method annotated with {@link com.facebook.litho.sections.annotations.OnCreateChildren}
   */
  protected Children createChildren(
      SectionContext c) {
    return null;
  }

  /**
   * This method will delegate to the {@link DiffSectionSpec}
   * method annotated with {@link OnDiff}
   */
  protected void generateChangeSet(
      SectionContext c,
      ChangeSet changeSet,
      Section previous,
      Section next) {
  }

  /**
   * This method will delegate to the {@link Section}Spec method annotated with {@link OnDataBound}
   */
  protected void dataBound(SectionContext c) {

  }

  protected void bindService(SectionContext c) {

  }

  protected void unbindService(SectionContext c) {

  }

  protected void createInitialState(SectionContext c) {

  }

  protected void createService(SectionContext c) {

  }

  @Override
  public Object dispatchOnEvent(EventHandler eventHandler, Object eventState) {
    // Do nothing by default.
    return null;
  }

  @Override
  @Nullable
  public Object acceptTriggerEvent(EventTrigger eventTrigger, Object eventState, Object[] params) {
    // Do nothing by default
    return null;
  }

  protected void viewportChanged(
      SectionContext sectionContext,
      int firstVisibleItem,
      int lastVisibleItem,
      int totalItemsCount,
      int firstFullyVisibleItem,
      int lastFullyVisibleItem) {

  }

  protected void refresh(SectionContext sectionContext) {

  }

  /**
   * Call this to transfer the {@link com.facebook.litho.annotations.State} annotated values
   * between two {@link Section} with the same global scope.
   */
  protected void transferState(
      SectionContext c,
      StateContainer stateContainer) {
  }

  /**
   * Call this to transfer the Services between two
   * {@link Section} with the same global scope.
   */
  protected void transferService(
      SectionContext c,
      Section oldSection,
      Section newSection) {
  }

  protected Object getService(Section section) {
    return null;
  }

  /**
   * @return Whether it's necessary to generate a new changeSet for the sub-tree with root in next
   * @param previous the {@link Section} with the same globalScope in the previous tree.
   * @param next the {@link Section} for which we want to check whether a new changeSet is needed.
   */
  final boolean shouldComponentUpdate(Section previous, Section next) {
    boolean dirty = false;

    // If next is invalidated it means a state update was applied to it so we need to create
    // the ChangeSet regardless.
    if (!dirty && next != null) {
      dirty |= next.isInvalidated();
    }

    return dirty || shouldUpdate(previous, next);
  }

  protected final <T> Diff<T> acquireDiff(T previousValue, T nextValue) {
    Diff diff = ComponentsPools.acquireDiff(previousValue, nextValue);

    return diff;
  }

  protected void releaseDiff(Diff diff) {
    ComponentsPools.release(diff);
  }

  protected Output acquireOutput() {
    //TODO 11953296
    return new Output();
  }

  protected void releaseOutput(Output output) {
    //TODO 11953296
  }

  protected boolean shouldUpdate(Section previous, Section next) {
    return !(previous == next || (previous != null && previous.isEquivalentTo(next)));
  }

  /**
   * @return true if this lifecycle will generate a changeSet. If false this lifecycle will instead
   * implement createChildren.
   */
  protected boolean isDiffSectionSpec() {
    return false;
  }


  String getLogTag() {
    return getClass().getSimpleName();
  }

  protected static <E> EventHandler<E> newEventHandler(
      SectionContext c,
      int id,
      Object[] params) {
    final EventHandler eventHandler = c.newEventHandler(id, params);
    recordEventHandler(c.getSectionScope(), eventHandler);

    return eventHandler;
  }

  protected static <E> EventHandler<E> newEventHandler(
      Section c,
      int id,
      Object[] params) {
    final EventHandler eventHandler = new EventHandler<E>(c, id, params);
    recordEventHandler(c, eventHandler);

    return eventHandler;
  }

  protected static <E> EventTrigger<E> newEventTrigger(SectionContext c, String childKey, int id) {
    return c.newEventTrigger(childKey, id);
  }

  @Nullable
  protected static EventTrigger getEventTrigger(SectionContext c, int id, String key) {
    if (c.getSectionScope() == null) {
      return null;
    }

    EventTrigger trigger =
        c.getSectionTree().getEventTrigger(c.getSectionScope().getGlobalKey() + id + key);

    if (trigger == null) {
      return null;
    }

    return trigger;
  }

  private static void recordEventHandler(Section section, EventHandler eventHandler) {
    section.getScopedContext().getSectionTree().recordEventHandler(section, eventHandler);
  }

  protected interface StateUpdate {
    void updateState(StateContainer stateContainer, Section section);
  }

  /**
   * Retrieves all of the tree props used by this Section from the TreeProps map
   * and sets the tree props as fields on the ComponentImpl.
   */
  protected void populateTreeProps(TreeProps parentTreeProps) {
  }

  /**
   * Updates the TreeProps map with outputs from all {@link OnCreateTreeProp} methods.
   */
  protected TreeProps getTreePropsForChildren(
      SectionContext c,
      TreeProps previousTreeProps) {
    return previousTreeProps;
  }

  public static EventHandler getLoadingEventHandler(SectionContext context) {
    Section scopedSection = context.getSectionScope();
    if (scopedSection == null) {
      return null;
    }

    while (scopedSection.getParent() != null) {
      if (scopedSection.loadingEventHandler != null) {
        return scopedSection.loadingEventHandler;
      }
      scopedSection = scopedSection.getParent();
    }

    return context.getTreeLoadingEventHandler();
  }

  public static void dispatchLoadingEvent(
      SectionContext context,
      boolean isEmpty,
      LoadingEvent.LoadingState loadingState,
      Throwable t) {
    final EventHandler<LoadingEvent> loadingEventHandler = getLoadingEventHandler(context);

    if (loadingEventHandler != null) {
      LoadingEvent loadingEvent = new LoadingEvent();
      loadingEvent.isEmpty = isEmpty;
      loadingEvent.loadingState = loadingState;
      loadingEvent.t = t;
      loadingEventHandler.dispatchEvent(loadingEvent);
    }
  }

  /** Scroll to the index of the section. */
  public static void requestFocus(SectionContext c, int index) {
    final Section scopedSection = c.getSectionScope();
    final SectionTree sectionTree = c.getSectionTree();

    if (scopedSection == null || sectionTree == null) {
      return;
    }

    sectionTree.requestFocus(scopedSection, index);
  }<commit_msg>Add @Nullable to throwable in SectionLifecycle.dispatchLoadingEvent<commit_after>/*
 * Copyright 2014-present Facebook, 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.facebook.litho.sections;

import android.support.annotation.Nullable;
import com.facebook.litho.ComponentsPools;
import com.facebook.litho.Diff;
import com.facebook.litho.EventDispatcher;
import com.facebook.litho.EventHandler;
import com.facebook.litho.EventTrigger;
import com.facebook.litho.EventTriggerTarget;
import com.facebook.litho.Output;
import com.facebook.litho.TreeProps;
import com.facebook.litho.annotations.OnCreateTreeProp;
import com.facebook.litho.sections.annotations.DiffSectionSpec;
import com.facebook.litho.sections.annotations.GroupSectionSpec;
import com.facebook.litho.sections.annotations.OnDataBound;
import com.facebook.litho.sections.annotations.OnDiff;

public abstract class SectionLifecycle implements EventDispatcher, EventTriggerTarget {

  protected interface StateContainer {}

  /**
   * This methods will delegate to the {@link GroupSectionSpec}
   * method annotated with {@link com.facebook.litho.sections.annotations.OnCreateChildren}
   */
  protected Children createChildren(
      SectionContext c) {
    return null;
  }

  /**
   * This method will delegate to the {@link DiffSectionSpec}
   * method annotated with {@link OnDiff}
   */
  protected void generateChangeSet(
      SectionContext c,
      ChangeSet changeSet,
      Section previous,
      Section next) {
  }

  /**
   * This method will delegate to the {@link Section}Spec method annotated with {@link OnDataBound}
   */
  protected void dataBound(SectionContext c) {

  }

  protected void bindService(SectionContext c) {

  }

  protected void unbindService(SectionContext c) {

  }

  protected void createInitialState(SectionContext c) {

  }

  protected void createService(SectionContext c) {

  }

  @Override
  public Object dispatchOnEvent(EventHandler eventHandler, Object eventState) {
    // Do nothing by default.
    return null;
  }

  @Override
  @Nullable
  public Object acceptTriggerEvent(EventTrigger eventTrigger, Object eventState, Object[] params) {
    // Do nothing by default
    return null;
  }

  protected void viewportChanged(
      SectionContext sectionContext,
      int firstVisibleItem,
      int lastVisibleItem,
      int totalItemsCount,
      int firstFullyVisibleItem,
      int lastFullyVisibleItem) {

  }

  protected void refresh(SectionContext sectionContext) {

  }

  /**
   * Call this to transfer the {@link com.facebook.litho.annotations.State} annotated values
   * between two {@link Section} with the same global scope.
   */
  protected void transferState(
      SectionContext c,
      StateContainer stateContainer) {
  }

  /**
   * Call this to transfer the Services between two
   * {@link Section} with the same global scope.
   */
  protected void transferService(
      SectionContext c,
      Section oldSection,
      Section newSection) {
  }

  protected Object getService(Section section) {
    return null;
  }

  /**
   * @return Whether it's necessary to generate a new changeSet for the sub-tree with root in next
   * @param previous the {@link Section} with the same globalScope in the previous tree.
   * @param next the {@link Section} for which we want to check whether a new changeSet is needed.
   */
  final boolean shouldComponentUpdate(Section previous, Section next) {
    boolean dirty = false;

    // If next is invalidated it means a state update was applied to it so we need to create
    // the ChangeSet regardless.
    if (!dirty && next != null) {
      dirty |= next.isInvalidated();
    }

    return dirty || shouldUpdate(previous, next);
  }

  protected final <T> Diff<T> acquireDiff(T previousValue, T nextValue) {
    Diff diff = ComponentsPools.acquireDiff(previousValue, nextValue);

    return diff;
  }

  protected void releaseDiff(Diff diff) {
    ComponentsPools.release(diff);
  }

  protected Output acquireOutput() {
    //TODO 11953296
    return new Output();
  }

  protected void releaseOutput(Output output) {
    //TODO 11953296
  }

  protected boolean shouldUpdate(Section previous, Section next) {
    return !(previous == next || (previous != null && previous.isEquivalentTo(next)));
  }

  /**
   * @return true if this lifecycle will generate a changeSet. If false this lifecycle will instead
   * implement createChildren.
   */
  protected boolean isDiffSectionSpec() {
    return false;
  }


  String getLogTag() {
    return getClass().getSimpleName();
  }

  protected static <E> EventHandler<E> newEventHandler(
      SectionContext c,
      int id,
      Object[] params) {
    final EventHandler eventHandler = c.newEventHandler(id, params);
    recordEventHandler(c.getSectionScope(), eventHandler);

    return eventHandler;
  }

  protected static <E> EventHandler<E> newEventHandler(
      Section c,
      int id,
      Object[] params) {
    final EventHandler eventHandler = new EventHandler<E>(c, id, params);
    recordEventHandler(c, eventHandler);

    return eventHandler;
  }

  protected static <E> EventTrigger<E> newEventTrigger(SectionContext c, String childKey, int id) {
    return c.newEventTrigger(childKey, id);
  }

  @Nullable
  protected static EventTrigger getEventTrigger(SectionContext c, int id, String key) {
    if (c.getSectionScope() == null) {
      return null;
    }

    EventTrigger trigger =
        c.getSectionTree().getEventTrigger(c.getSectionScope().getGlobalKey() + id + key);

    if (trigger == null) {
      return null;
    }

    return trigger;
  }

  private static void recordEventHandler(Section section, EventHandler eventHandler) {
    section.getScopedContext().getSectionTree().recordEventHandler(section, eventHandler);
  }

  protected interface StateUpdate {
    void updateState(StateContainer stateContainer, Section section);
  }

  /**
   * Retrieves all of the tree props used by this Section from the TreeProps map
   * and sets the tree props as fields on the ComponentImpl.
   */
  protected void populateTreeProps(TreeProps parentTreeProps) {
  }

  /**
   * Updates the TreeProps map with outputs from all {@link OnCreateTreeProp} methods.
   */
  protected TreeProps getTreePropsForChildren(
      SectionContext c,
      TreeProps previousTreeProps) {
    return previousTreeProps;
  }

  public static EventHandler getLoadingEventHandler(SectionContext context) {
    Section scopedSection = context.getSectionScope();
    if (scopedSection == null) {
      return null;
    }

    while (scopedSection.getParent() != null) {
      if (scopedSection.loadingEventHandler != null) {
        return scopedSection.loadingEventHandler;
      }
      scopedSection = scopedSection.getParent();
    }

    return context.getTreeLoadingEventHandler();
  }

  public static void dispatchLoadingEvent(
      SectionContext context,
      boolean isEmpty,
      LoadingEvent.LoadingState loadingState,
      @Nullable Throwable t) {
    final EventHandler<LoadingEvent> loadingEventHandler = getLoadingEventHandler(context);

    if (loadingEventHandler != null) {
      LoadingEvent loadingEvent = new LoadingEvent();
      loadingEvent.isEmpty = isEmpty;
      loadingEvent.loadingState = loadingState;
      loadingEvent.t = t;
      loadingEventHandler.dispatchEvent(loadingEvent);
    }
  }

  /** Scroll to the index of the section. */
  public static void requestFocus(SectionContext c, int index) {
    final Section scopedSection = c.getSectionScope();
    final SectionTree sectionTree = c.getSectionTree();

    if (scopedSection == null || sectionTree == null) {
      return;
    }

    sectionTree.requestFocus(scopedSection, index);
  }
{'fraction_non_alphanumeric': 0.08408317120622569, 'fraction_numerical': 0.0029182879377431907, 'mean_word_length': 3.569166666666667, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1922627', 'n_tokens_mistral': 4504, 'n_tokens_neox': 4360, 'n_words': 1390}