<commit_before>// Copyright (C) 2013 The Android Open Source Project
//
// 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.google.gerrit.client.change;

import static com.google.gerrit.common.PageLinks.op;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeList;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TabPanel;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public class RelatedChanges extends TabPanel {
  static final RelatedChangesResources R = GWT
      .create(RelatedChangesResources.class);

  interface RelatedChangesResources extends ClientBundle {
    @Source("related_changes.css")
    RelatedChangesCss css();
  }

  interface RelatedChangesCss extends CssResource {
    String activeRow();
    String current();
    String gitweb();
    String indirect();
    String notCurrent();
    String pointer();
    String row();
    String subject();
    String strikedSubject();
    String submittable();
    String tabPanel();
  }

  enum Tab {
    RELATED_CHANGES(Resources.C.relatedChanges(),
        Resources.C.relatedChangesTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.relatedChanges(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.relatedChanges(count);
      }
    },

    SUBMITTED_TOGETHER(Resources.C.submittedTogether(),
        Resources.C.submittedTogether()) {
      @Override
      String getTitle(int count) {
        return Resources.M.submittedTogether(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.submittedTogether(count);
      }
    },

    SAME_TOPIC(Resources.C.sameTopic(),
        Resources.C.sameTopicTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.sameTopic(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.sameTopic(count);
      }
    },

    CONFLICTING_CHANGES(Resources.C.conflictingChanges(),
        Resources.C.conflictingChangesTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.conflictingChanges(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.conflictingChanges(count);
      }
    },

    CHERRY_PICKS(Resources.C.cherryPicks(),
        Resources.C.cherryPicksTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.cherryPicks(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.cherryPicks(count);
      }
    };

    final String defaultTitle;
    final String tooltip;

    abstract String getTitle(int count);
    abstract String getTitle(String count);

    private Tab(String defaultTitle, String tooltip) {
      this.defaultTitle = defaultTitle;
      this.tooltip = tooltip;
    }
  }

  private static Tab savedTab;

  private final List<RelatedChangesTab> tabs;
  private int maxHeightWithHeader;
  private int selectedTab;
  private int outstandingCallbacks;

  RelatedChanges() {
    tabs = new ArrayList<>(Tab.values().length);
    selectedTab = -1;

    setVisible(false);
    addStyleName(R.css().tabPanel());
    initTabBar();
  }

  private void initTabBar() {
    TabBar tabBar = getTabBar();
    tabBar.addSelectionHandler(new SelectionHandler<Integer>() {
      @Override
      public void onSelection(SelectionEvent<Integer> event) {
        if (selectedTab >= 0) {
          tabs.get(selectedTab).registerKeys(false);
        }
        selectedTab = event.getSelectedItem();
        tabs.get(selectedTab).registerKeys(true);
      }
    });

    for (Tab tabInfo : Tab.values()) {
      RelatedChangesTab panel = new RelatedChangesTab(tabInfo);
      add(panel, tabInfo.defaultTitle);
      tabs.add(panel);

      TabBar.Tab tab = tabBar.getTab(tabInfo.ordinal());
      tab.setWordWrap(false);
      ((Composite) tab).setTitle(tabInfo.tooltip);

      setTabEnabled(tabInfo, false);
    }
    getTab(Tab.RELATED_CHANGES).setShowIndirectAncestors(true);
    getTab(Tab.CHERRY_PICKS).setShowBranches(true);
    getTab(Tab.SAME_TOPIC).setShowBranches(true);
    getTab(Tab.SAME_TOPIC).setShowProjects(true);
    getTab(Tab.SAME_TOPIC).setShowSubmittable(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowBranches(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowProjects(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowSubmittable(true);
  }

  void set(final ChangeInfo info, final String revision) {
    if (info.status().isOpen()) {
      setForOpenChange(info, revision);
    }

    ChangeApi.revision(info.legacyId().get(), revision).view("related")
        .get(new TabCallback<RelatedInfo>(Tab.RELATED_CHANGES, info.project(), revision) {
              @Override
              public JsArray<ChangeAndCommit> convert(RelatedInfo result) {
                return result.changes();
              }
            });

    StringBuilder cherryPicksQuery = new StringBuilder();
    cherryPicksQuery.append(op("project", info.project()));
    cherryPicksQuery.append(" ").append(op("change", info.changeId()));
    cherryPicksQuery.append(" ").append(op("-change", info.legacyId().get()));
    cherryPicksQuery.append(" -is:abandoned");
    ChangeList.query(cherryPicksQuery.toString(),
        EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
        new TabChangeListCallback(Tab.CHERRY_PICKS, info.project(), revision));

    if (!Gerrit.info().change().isSubmitWholeTopicEnabled()
        && info.topic() != null && !"".equals(info.topic())) {
      StringBuilder topicQuery = new StringBuilder();
      topicQuery.append("status:open");
      topicQuery.append(" ").append(op("topic", info.topic()));
      ChangeList.query(topicQuery.toString(),
          EnumSet.of(ListChangesOption.CURRENT_REVISION,
                     ListChangesOption.CURRENT_COMMIT,
                     ListChangesOption.DETAILED_LABELS,
                     ListChangesOption.LABELS),
          new TabChangeListCallback(Tab.SAME_TOPIC, info.project(), revision));
    } else {
      // TODO(sbeller): show only on latest revision
      ChangeApi.change(info.legacyId().get()).view("submitted_together")
          .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER,
              info.project(), revision));
    }
  }

  private void setForOpenChange(final ChangeInfo info, final String revision) {
    if (info.mergeable()) {
      StringBuilder conflictsQuery = new StringBuilder();
      conflictsQuery.append("status:open");
      conflictsQuery.append(" is:mergeable");
      conflictsQuery.append(" ").append(op("conflicts", info.legacyId().get()));
      ChangeList.query(conflictsQuery.toString(),
          EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
          new TabChangeListCallback(Tab.CONFLICTING_CHANGES, info.project(), revision));
    }
  }

  @Override
  protected void onLoad() {
    super.onLoad();
    R.css().ensureInjected();
  }

  static void setSavedTab(Tab subject) {<commit_msg>RelatedChanges: Show "Submitted Together" also for changes with topic<commit_after>// Copyright (C) 2013 The Android Open Source Project
//
// 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.google.gerrit.client.change;

import static com.google.gerrit.common.PageLinks.op;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeList;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TabPanel;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public class RelatedChanges extends TabPanel {
  static final RelatedChangesResources R = GWT
      .create(RelatedChangesResources.class);

  interface RelatedChangesResources extends ClientBundle {
    @Source("related_changes.css")
    RelatedChangesCss css();
  }

  interface RelatedChangesCss extends CssResource {
    String activeRow();
    String current();
    String gitweb();
    String indirect();
    String notCurrent();
    String pointer();
    String row();
    String subject();
    String strikedSubject();
    String submittable();
    String tabPanel();
  }

  enum Tab {
    RELATED_CHANGES(Resources.C.relatedChanges(),
        Resources.C.relatedChangesTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.relatedChanges(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.relatedChanges(count);
      }
    },

    SUBMITTED_TOGETHER(Resources.C.submittedTogether(),
        Resources.C.submittedTogether()) {
      @Override
      String getTitle(int count) {
        return Resources.M.submittedTogether(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.submittedTogether(count);
      }
    },

    SAME_TOPIC(Resources.C.sameTopic(),
        Resources.C.sameTopicTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.sameTopic(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.sameTopic(count);
      }
    },

    CONFLICTING_CHANGES(Resources.C.conflictingChanges(),
        Resources.C.conflictingChangesTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.conflictingChanges(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.conflictingChanges(count);
      }
    },

    CHERRY_PICKS(Resources.C.cherryPicks(),
        Resources.C.cherryPicksTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.cherryPicks(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.cherryPicks(count);
      }
    };

    final String defaultTitle;
    final String tooltip;

    abstract String getTitle(int count);
    abstract String getTitle(String count);

    private Tab(String defaultTitle, String tooltip) {
      this.defaultTitle = defaultTitle;
      this.tooltip = tooltip;
    }
  }

  private static Tab savedTab;

  private final List<RelatedChangesTab> tabs;
  private int maxHeightWithHeader;
  private int selectedTab;
  private int outstandingCallbacks;

  RelatedChanges() {
    tabs = new ArrayList<>(Tab.values().length);
    selectedTab = -1;

    setVisible(false);
    addStyleName(R.css().tabPanel());
    initTabBar();
  }

  private void initTabBar() {
    TabBar tabBar = getTabBar();
    tabBar.addSelectionHandler(new SelectionHandler<Integer>() {
      @Override
      public void onSelection(SelectionEvent<Integer> event) {
        if (selectedTab >= 0) {
          tabs.get(selectedTab).registerKeys(false);
        }
        selectedTab = event.getSelectedItem();
        tabs.get(selectedTab).registerKeys(true);
      }
    });

    for (Tab tabInfo : Tab.values()) {
      RelatedChangesTab panel = new RelatedChangesTab(tabInfo);
      add(panel, tabInfo.defaultTitle);
      tabs.add(panel);

      TabBar.Tab tab = tabBar.getTab(tabInfo.ordinal());
      tab.setWordWrap(false);
      ((Composite) tab).setTitle(tabInfo.tooltip);

      setTabEnabled(tabInfo, false);
    }
    getTab(Tab.RELATED_CHANGES).setShowIndirectAncestors(true);
    getTab(Tab.CHERRY_PICKS).setShowBranches(true);
    getTab(Tab.SAME_TOPIC).setShowBranches(true);
    getTab(Tab.SAME_TOPIC).setShowProjects(true);
    getTab(Tab.SAME_TOPIC).setShowSubmittable(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowBranches(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowProjects(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowSubmittable(true);
  }

  void set(final ChangeInfo info, final String revision) {
    if (info.status().isOpen()) {
      setForOpenChange(info, revision);
    }

    ChangeApi.revision(info.legacyId().get(), revision).view("related")
        .get(new TabCallback<RelatedInfo>(Tab.RELATED_CHANGES, info.project(), revision) {
              @Override
              public JsArray<ChangeAndCommit> convert(RelatedInfo result) {
                return result.changes();
              }
            });

    StringBuilder cherryPicksQuery = new StringBuilder();
    cherryPicksQuery.append(op("project", info.project()));
    cherryPicksQuery.append(" ").append(op("change", info.changeId()));
    cherryPicksQuery.append(" ").append(op("-change", info.legacyId().get()));
    cherryPicksQuery.append(" -is:abandoned");
    ChangeList.query(cherryPicksQuery.toString(),
        EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
        new TabChangeListCallback(Tab.CHERRY_PICKS, info.project(), revision));

    // TODO(sbeller): show only on latest revision
    ChangeApi.change(info.legacyId().get()).view("submitted_together")
        .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER,
            info.project(), revision));

    if (!Gerrit.info().change().isSubmitWholeTopicEnabled()
        && info.topic() != null && !"".equals(info.topic())) {
      StringBuilder topicQuery = new StringBuilder();
      topicQuery.append("status:open");
      topicQuery.append(" ").append(op("topic", info.topic()));
      ChangeList.query(topicQuery.toString(),
          EnumSet.of(ListChangesOption.CURRENT_REVISION,
                     ListChangesOption.CURRENT_COMMIT,
                     ListChangesOption.DETAILED_LABELS,
                     ListChangesOption.LABELS),
          new TabChangeListCallback(Tab.SAME_TOPIC, info.project(), revision));
    }
  }

  private void setForOpenChange(final ChangeInfo info, final String revision) {
    if (info.mergeable()) {
      StringBuilder conflictsQuery = new StringBuilder();
      conflictsQuery.append("status:open");
      conflictsQuery.append(" is:mergeable");
      conflictsQuery.append(" ").append(op("conflicts", info.legacyId().get()));
      ChangeList.query(conflictsQuery.toString(),
          EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
          new TabChangeListCallback(Tab.CONFLICTING_CHANGES, info.project(), revision));
    }
  }

  @Override
  protected void onLoad() {
    super.onLoad();
    R.css().ensureInjected();
  }

  static void setSavedTab(Tab subject) {
{'fraction_non_alphanumeric': 0.11688235979946368, 'fraction_numerical': 0.0011659088259298124, 'mean_word_length': 3.4202525122391134, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5714051', 'n_tokens_mistral': 5113, 'n_tokens_neox': 4989, 'n_words': 943}