public void testResourceBundleManagerUpdatesProperlyWhileDirRemoval() {
    myFixture.addFileToProject("qwe/asd/p.properties", "");
    final PsiFile file = myFixture.addFileToProject("qwe/asd/p_en.properties", "");
    final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
    assertNotNull(propertiesFile);
    final ResourceBundleManager resourceBundleManager =
        ResourceBundleManager.getInstance(getProject());
    resourceBundleManager.dissociateResourceBundle(propertiesFile.getResourceBundle());

    final PropertiesFile propFile1 =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("qwe1/asd1/p.properties", ""));
    final PropertiesFile propFile2 =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("qwe1/asd1/p_abc.properties", ""));
    assertNotNull(propFile1);
    assertNotNull(propFile2);
    resourceBundleManager.combineToResourceBundle(
        ContainerUtil.newArrayList(propFile1, propFile2), "p");

    final PsiFile someFile = myFixture.addFileToProject("to_remove/asd.txt", "");
    final PsiDirectory toRemove = someFile.getParent();
    assertNotNull(toRemove);
    ApplicationManager.getApplication().runWriteAction(toRemove::delete);

    final ResourceBundleManagerState state = resourceBundleManager.getState();
    assertNotNull(state);
    assertSize(1, state.getCustomResourceBundles());
    assertSize(2, state.getDissociatedFiles());

    final PsiDirectory directory = propertiesFile.getParent().getParent();
    assertNotNull(directory);
    ApplicationManager.getApplication().runWriteAction(directory::delete);

    assertSize(1, state.getCustomResourceBundles());
    assertSize(0, state.getDissociatedFiles());

    final PsiDirectory directory1 = propFile1.getParent().getParent();
    assertNotNull(directory1);
    ApplicationManager.getApplication().runWriteAction(directory1::delete);

    assertSize(0, state.getCustomResourceBundles());
    assertSize(0, state.getDissociatedFiles());
  }
  public void testCustomResourceBundleFilesMovedOrDeleted() throws IOException {
    final PropertiesFile file =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("resources-dev/my-app-dev.properties", ""));
    final PropertiesFile file2 =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("resources-dev/my-app-test.properties", ""));
    final PropertiesFile file3 =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("resources-prod/my-app-prod.properties", ""));
    assertNotNull(file);
    assertNotNull(file2);
    assertNotNull(file3);
    assertOneElement(file.getResourceBundle().getPropertiesFiles());
    assertOneElement(file2.getResourceBundle().getPropertiesFiles());
    assertOneElement(file3.getResourceBundle().getPropertiesFiles());
    final ResourceBundleManager resourceBundleBaseNameManager =
        ResourceBundleManager.getInstance(getProject());
    resourceBundleBaseNameManager.combineToResourceBundle(list(file, file2, file3), "my-app");

    assertSize(3, file.getResourceBundle().getPropertiesFiles());

    final PsiDirectory newDir =
        PsiManager.getInstance(getProject())
            .findDirectory(myFixture.getTempDirFixture().findOrCreateDir("new-resources-dir"));
    new MoveFilesOrDirectoriesProcessor(
            getProject(),
            new PsiElement[] {file2.getContainingFile()},
            newDir,
            false,
            false,
            null,
            null)
        .run();
    ApplicationManager.getApplication().runWriteAction(() -> file3.getContainingFile().delete());

    assertSize(2, file.getResourceBundle().getPropertiesFiles());

    final ResourceBundleManagerState state =
        ResourceBundleManager.getInstance(getProject()).getState();
    assertNotNull(state);
    assertSize(1, state.getCustomResourceBundles());
    assertSize(2, state.getCustomResourceBundles().get(0).getFileUrls());
  }
  public void testResourceBundleManagerUpdatesProperlyWhileDirMove() {
    final PropertiesFile propFile1 =
        PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("qwe/p.properties", ""));
    final PropertiesFile propFile2 =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("qwe/p_abc.properties", ""));
    assertNotNull(propFile1);
    assertNotNull(propFile2);
    myFixture.addFileToProject("qwe/q.properties", "");
    final PropertiesFile propertiesFile =
        PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("qwe/q_fr.properties", ""));
    assertNotNull(propertiesFile);
    assertSize(2, propertiesFile.getResourceBundle().getPropertiesFiles());

    final ResourceBundleManager resourceBundleManager =
        ResourceBundleManager.getInstance(getProject());
    resourceBundleManager.combineToResourceBundle(
        ContainerUtil.newArrayList(propFile1, propFile2), "p");
    resourceBundleManager.dissociateResourceBundle(propertiesFile.getResourceBundle());
    assertSize(1, propertiesFile.getResourceBundle().getPropertiesFiles());
    assertSize(2, propFile2.getResourceBundle().getPropertiesFiles());

    final PsiDirectory toMove = myFixture.addFileToProject("asd/temp.txt", "").getParent();
    assertNotNull(toMove);
    ApplicationManager.getApplication()
        .runWriteAction(
            () -> MoveFilesOrDirectoriesUtil.doMoveDirectory(propFile1.getParent(), toMove));

    final PsiDirectory movedDir = toMove.findSubdirectory("qwe");
    assertNotNull(movedDir);

    final PropertiesFile newPropFile1 =
        PropertiesImplUtil.getPropertiesFile(movedDir.findFile("p.properties"));
    assertNotNull(newPropFile1);
    assertSize(2, newPropFile1.getResourceBundle().getPropertiesFiles());

    final PropertiesFile newPropertiesFile =
        PropertiesImplUtil.getPropertiesFile(movedDir.findFile("q_fr.properties"));
    assertNotNull(newPropertiesFile);
    assertSize(1, newPropertiesFile.getResourceBundle().getPropertiesFiles());
  }
  private void combineToResourceBundleIfNeed(Collection<PsiFile> files) {
    Collection<PropertiesFile> createdFiles =
        ContainerUtil.map(
            files,
            (NotNullFunction<PsiFile, PropertiesFile>)
                dom -> {
                  final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(dom);
                  LOG.assertTrue(file != null, dom.getName());
                  return file;
                });

    ResourceBundle mainBundle = myResourceBundle;
    final Set<ResourceBundle> allBundles = new HashSet<>();
    if (mainBundle != null) {
      allBundles.add(mainBundle);
    }
    boolean needCombining = false;
    for (PropertiesFile file : createdFiles) {
      final ResourceBundle rb = file.getResourceBundle();
      if (mainBundle == null) {
        mainBundle = rb;
      } else if (!mainBundle.equals(rb)) {
        needCombining = true;
      }
      allBundles.add(rb);
    }

    if (needCombining) {
      final List<PropertiesFile> toCombine = new ArrayList<>(createdFiles);
      final String baseName = getBaseName();
      if (myResourceBundle != null) {
        toCombine.addAll(myResourceBundle.getPropertiesFiles());
      }
      ResourceBundleManager manager = ResourceBundleManager.getInstance(mainBundle.getProject());
      for (ResourceBundle bundle : allBundles) {
        manager.dissociateResourceBundle(bundle);
      }
      manager.combineToResourceBundle(toCombine, baseName);
    }
  }
  public void testLanguageCodeNotRecognized() {
    final PsiFile file = myFixture.addFileToProject("p.properties", "");
    final PsiFile file2 = myFixture.addFileToProject("p_asd.properties", "");

    final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
    final PropertiesFile propertiesFile2 = PropertiesImplUtil.getPropertiesFile(file2);
    assertNotNull(propertiesFile);
    assertNotNull(propertiesFile2);
    final ResourceBundle bundle = propertiesFile.getResourceBundle();
    final ResourceBundle bundle2 = propertiesFile2.getResourceBundle();
    assertSize(1, bundle.getPropertiesFiles());
    assertSize(1, bundle2.getPropertiesFiles());
    assertEquals("p", bundle.getBaseName());
    assertEquals("p_asd", bundle2.getBaseName());

    final ResourceBundleManager manager = ResourceBundleManager.getInstance(getProject());
    final ArrayList<PropertiesFile> rawBundle =
        ContainerUtil.newArrayList(propertiesFile, propertiesFile2);
    final String suggestedBaseName = PropertiesUtil.getDefaultBaseName(rawBundle);
    assertEquals("p", suggestedBaseName);
    manager.combineToResourceBundle(rawBundle, suggestedBaseName);

    assertEquals("asd", propertiesFile2.getLocale().getLanguage());
  }
  public void testCombineToCustomResourceBundleAndDissociateAfter() {
    final PropertiesFile file =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("resources-dev/my-app-dev.properties", ""));
    final PropertiesFile file2 =
        PropertiesImplUtil.getPropertiesFile(
            myFixture.addFileToProject("resources-prod/my-app-prod.properties", ""));
    assertNotNull(file);
    assertNotNull(file2);
    assertOneElement(file.getResourceBundle().getPropertiesFiles());
    assertOneElement(file2.getResourceBundle().getPropertiesFiles());

    final ResourceBundleManager resourceBundleBaseNameManager =
        ResourceBundleManager.getInstance(getProject());
    final String newBaseName = "my-app";
    resourceBundleBaseNameManager.combineToResourceBundle(list(file, file2), newBaseName);
    final ResourceBundle resourceBundle = file.getResourceBundle();
    assertEquals(2, resourceBundle.getPropertiesFiles().size());
    assertEquals(newBaseName, resourceBundle.getBaseName());

    resourceBundleBaseNameManager.dissociateResourceBundle(resourceBundle);
    assertOneElement(file.getResourceBundle().getPropertiesFiles());
    assertOneElement(file2.getResourceBundle().getPropertiesFiles());
  }
/** Represents the data table model for the Configuration dialog. */
public class ConfigurationTableModel extends DataTableModel<ConfigurationData> {
  private static final long serialVersionUID = 1L;

  private static final ResourceBundle rb = ResourceBundleManager.getDefaultBundle();

  /** An integer that identifies the attribute column. */
  public static final int PROFILE_ATTRIBUTE_COLUMN = 0;
  /** An integer that identifies the data column. */
  public static final int PROFILE_DATA_COLUMN = 1;

  private static final String[] columns = {
    rb.getString("configurationTableModel.PROFILE_ATTRIBUTE_COLUMN"),
    rb.getString("configurationTableModel.PROFILE_DATA_COLUMN")
  };

  private File file;
  private String name;
  private ProfileType profileType;

  /** Initializes a new instance of the ConfigurationTableModel class. */
  public ConfigurationTableModel() {
    super(columns);
  }

  /**
   * Initializes a new instance of the ConfigurationTableModel class using the specified profile.
   * Sets the default profile for the Configuration table.
   *
   * @param profile - The new default profile for the Configuration table.
   * @see Profile
   */
  public ConfigurationTableModel(Profile profile) {
    super(columns);
    setProfile(profile);
  }

  /**
   * Sets the profile data for the Configuration table model.
   *
   * @param profile - The profile for the Configuration table.
   */
  public synchronized void setProfile(Profile profile) {
    this.file = profile.getFile();
    this.name = profile.getName();
    List<ConfigurationData> data = new ArrayList<ConfigurationData>();

    if (profile instanceof Profile3G) {
      this.profileType = ProfileType.T3G;
    } else if (profile instanceof ProfileLTE) {
      this.profileType = ProfileType.LTE;
    } else {
      throw new IllegalArgumentException("Invalid Profile type");
    }

    data.add(
        new ConfigurationData(
            rb.getString("configuration.CARRIER"), Profile.CARRIER, profile.getCarrier()));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.DEVICE"), Profile.DEVICE, profile.getDevice()));

    if (profile instanceof Profile3G) {
      // Adding 3G Profile
      Profile3G profile3g = (Profile3G) profile;

      data.add(
          new ConfigurationData(
              rb.getString("configuration.DCH_FACH_TIMER"),
              Profile3G.DCH_FACH_TIMER,
              Double.toString(profile3g.getDchFachTimer())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.FACH_IDLE_TIMER"),
              Profile3G.FACH_IDLE_TIMER,
              Double.toString(profile3g.getFachIdleTimer())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.IDLE_DCH_PROMO_MIN"),
              Profile3G.IDLE_DCH_PROMO_MIN,
              Double.toString(profile3g.getIdleDchPromoMin())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.IDLE_DCH_PROMO_AVG"),
              Profile3G.IDLE_DCH_PROMO_AVG,
              Double.toString(profile3g.getIdleDchPromoAvg())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.IDLE_DCH_PROMO_MAX"),
              Profile3G.IDLE_DCH_PROMO_MAX,
              Double.toString(profile3g.getIdleDchPromoMax())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.FACH_DCH_PROMO_MIN"),
              Profile3G.FACH_DCH_PROMO_MIN,
              Double.toString(profile3g.getFachDchPromoMin())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.FACH_DCH_PROMO_AVG"),
              Profile3G.FACH_DCH_PROMO_AVG,
              Double.toString(profile3g.getFachDchPromoAvg())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.FACH_DCH_PROMO_MAX"),
              Profile3G.FACH_DCH_PROMO_MAX,
              Double.toString(profile3g.getFachDchPromoMax())));

      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_UL_TH"),
              Profile3G.RLC_UL_TH,
              Integer.toString(profile3g.getRlcUlTh())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_DL_TH"),
              Profile3G.RLC_DL_TH,
              Integer.toString(profile3g.getRlcDlTh())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.DCH_TIMER_RESET_SIZE"),
              Profile3G.DCH_TIMER_RESET_SIZE,
              Integer.toString(profile3g.getDchTimerResetSize())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.DCH_TIMER_RESET_WIN"),
              Profile3G.DCH_TIMER_RESET_WIN,
              Double.toString(profile3g.getDchTimerResetWin())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_UL_RATE_P2"),
              Profile3G.RLC_UL_RATE_P2,
              Double.toString(profile3g.getRlcUlRateP2())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_UL_RATE_P1"),
              Profile3G.RLC_UL_RATE_P1,
              Double.toString(profile3g.getRlcUlRateP1())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_UL_RATE_P0"),
              Profile3G.RLC_UL_RATE_P0,
              Double.toString(profile3g.getRlcUlRateP0())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_DL_RATE_P2"),
              Profile3G.RLC_DL_RATE_P2,
              Double.toString(profile3g.getRlcDlRateP2())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_DL_RATE_P1"),
              Profile3G.RLC_DL_RATE_P1,
              Double.toString(profile3g.getRlcDlRateP1())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.RLC_DL_RATE_P0"),
              Profile3G.RLC_DL_RATE_P0,
              Double.toString(profile3g.getRlcDlRateP0())));

      data.add(
          new ConfigurationData(
              rb.getString("configuration.POWER_DCH"),
              Profile3G.POWER_DCH,
              Double.toString(profile3g.getPowerDch())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.POWER_FACH"),
              Profile3G.POWER_FACH,
              Double.toString(profile3g.getPowerFach())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.POWER_IDLE"),
              Profile3G.POWER_IDLE,
              Double.toString(profile3g.getPowerIdle())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.POWER_IDLE_DCH"),
              Profile3G.POWER_IDLE_DCH,
              Double.toString(profile3g.getPowerIdleDch())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.POWER_FACH_DCH"),
              Profile3G.POWER_FACH_DCH,
              Double.toString(profile3g.getPowerFachDch())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.W_THROUGHPUT"),
              ProfileLTE.W_THROUGHPUT,
              Double.toString(profile3g.getThroughputWindow())));
    } else if (profile instanceof ProfileLTE) {

      // Adding LTE Parameters
      ProfileLTE profileLte = (ProfileLTE) profile;
      data.add(
          new ConfigurationData(
              rb.getString("configuration.T_PROMOTION"),
              ProfileLTE.T_PROMOTION,
              Double.toString(profileLte.getPromotionTime())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.TI_DRX"),
              ProfileLTE.INACTIVITY_TIMER,
              Double.toString(profileLte.getInactivityTimer())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.TIS_DRX"),
              ProfileLTE.T_SHORT_DRX,
              Double.toString(profileLte.getDrxShortTime())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.TON_DRX"),
              ProfileLTE.T_DRX_PING,
              Double.toString(profileLte.getDrxPingTime())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.T_TAIL_DRX"),
              ProfileLTE.T_LONG_DRX,
              Double.toString(profileLte.getDrxLongTime())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.T_ONIDLE"),
              ProfileLTE.T_IDLE_PING,
              Double.toString(profileLte.getIdlePingTime())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.TPS_DRX"),
              ProfileLTE.T_SHORT_DRX_PING_PERIOD,
              Double.toString(profileLte.getDrxShortPingPeriod())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.TPI_DRX"),
              ProfileLTE.T_LONG_DRX_PING_PERIOD,
              Double.toString(profileLte.getDrxLongPingPeriod())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.PPL_DRX"),
              ProfileLTE.T_IDLE_PING_PERIOD,
              Double.toString(profileLte.getIdlePingPeriod())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.W_THROUGHPUT"),
              ProfileLTE.W_THROUGHPUT,
              Double.toString(profileLte.getThroughputWindow())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_P_PROMOTION"),
              ProfileLTE.P_PROMOTION,
              Double.toString(profileLte.getLtePromotionPower())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_P_SHORT_DRX"),
              ProfileLTE.P_SHORT_DRX_PING,
              Double.toString(profileLte.getDrxShortPingPower())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_LONG_DRX"),
              ProfileLTE.P_LONG_DRX_PING,
              Double.toString(profileLte.getDrxLongPingPower())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_TAIL"),
              ProfileLTE.P_TAIL,
              Double.toString(profileLte.getLteTailPower())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_IDLE"),
              ProfileLTE.P_IDLE_PING,
              Double.toString(profileLte.getLteIdlePingPower())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_ALPHA_UP"),
              ProfileLTE.LTE_ALPHA_UP,
              Double.toString(profileLte.getLteAlphaUp())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_ALPHA_DOWN"),
              ProfileLTE.LTE_ALPHA_DOWN,
              Double.toString(profileLte.getLteAlphaDown())));
      data.add(
          new ConfigurationData(
              rb.getString("configuration.LTE_BETA"),
              ProfileLTE.LTE_BETA,
              Double.toString(profileLte.getLteBeta())));
    }

    data.add(
        new ConfigurationData(
            rb.getString("configuration.BURST_TH"),
            Profile.BURST_TH,
            Double.toString(profile.getBurstTh())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.LONG_BURST_TH"),
            Profile.LONG_BURST_TH,
            Double.toString(profile.getLongBurstTh())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.USER_INPUT_TH"),
            Profile.USER_INPUT_TH,
            Double.toString(profile.getUserInputTh())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.PERIOD_MIN_CYCLE"),
            Profile.PERIOD_MIN_CYCLE,
            Double.toString(profile.getPeriodMinCycle())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.PERIOD_CYCLE_TOL"),
            Profile.PERIOD_CYCLE_TOL,
            Double.toString(profile.getPeriodCycleTol())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.PERIOD_MIN_SAMPLES"),
            Profile.PERIOD_MIN_SAMPLES,
            Integer.toString(profile.getPeriodMinSamples())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.LARGE_BURST_DURATION"),
            Profile.LARGE_BURST_DURATION,
            Double.toString(profile.getLargeBurstDuration())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.LARGE_BURST_SIZE"),
            Profile.LARGE_BURST_SIZE,
            Integer.toString(profile.getLargeBurstSize())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_GPS_ACTIVE"),
            Profile.POWER_GPS_ACTIVE,
            Double.toString(profile.getPowerGpsActive())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_GPS_STANDBY"),
            Profile.POWER_GPS_STANDBY,
            Double.toString(profile.getPowerGpsStandby())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_CAMERA_ON"),
            Profile.POWER_CAMERA_ON,
            Double.toString(profile.getPowerCameraOn())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_WIFI_ACTIVE"),
            Profile.POWER_WIFI_ACTIVE,
            Double.toString(profile.getPowerWifiActive())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_WIFI_STANDBY"),
            Profile.POWER_WIFI_STANDBY,
            Double.toString(profile.getPowerWifiStandby())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_BLUETOOTH_ACTIVE"),
            Profile.POWER_BLUETOOTH_ACTIVE,
            Double.toString(profile.getPowerBluetoothActive())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_BLUETOOTH_STANDBY"),
            Profile.POWER_BLUETOOTH_STANDBY,
            Double.toString(profile.getPowerBluetoothStandby())));
    data.add(
        new ConfigurationData(
            rb.getString("configuration.POWER_SCREEN_ON"),
            Profile.POWER_SCREEN_ON,
            Double.toString(profile.getPowerScreenOn())));
    setData(data);
  }

  /**
   * Returns the profile represented by this table model.
   *
   * @return The profile for the Configuration table.
   * @throws ProfileException
   */
  public Profile getProfile() throws ProfileException {
    Properties props = new Properties();
    for (ConfigurationData data : getData()) {
      String value = data.getProfileData();
      String attribute = data.getProfileAttr();
      if (value != null) {
        props.setProperty(attribute, value);
      }
    }

    Profile profile = null;
    switch (profileType) {
      case T3G:
        if (file != null) {
          profile = new Profile3G(file, props);
        } else {
          profile = new Profile3G(name, props);
        }
        break;
      case LTE:
        if (file != null) {
          profile = new ProfileLTE(file, props);
        } else {
          profile = new ProfileLTE(name, props);
        }
        break;
    }
    return profile;
  }

  @Override
  protected Object getColumnValue(ConfigurationData item, int columnIndex) {
    switch (columnIndex) {
      case PROFILE_ATTRIBUTE_COLUMN:
        return item.getProfileDesc();
      case PROFILE_DATA_COLUMN:
        return item.getProfileData();
    }
    return null;
  }

  /**
   * Returns a value that indicates whether the specified data cell is editable or not.
   *
   * @param row – The row number of the cell.
   * @param col – The column number of the cell.
   * @return A boolean value that is “true” if the cell is editable, and “false” if it is not.
   */
  @Override
  public boolean isCellEditable(int row, int col) {

    return col == PROFILE_DATA_COLUMN;
  }

  /**
   * Sets the value of the specified profile data item.
   *
   * @param Value – The value to set for the data item.
   * @param rowIndex – The row index of the data item.
   * @param columnIndex - The column index of the data item.
   */
  @Override
  public void setValueAt(Object value, int rowIndex, int columnIndex) {
    // data[rowIndex][columnIndex] = value;
    // fireTableCellUpdated(rowIndex, columnIndex);
    super.setValueAt(value, rowIndex, columnIndex);

    if (columnIndex == PROFILE_DATA_COLUMN) {
      String s = value.toString();
      ConfigurationData cd = getValueAt(rowIndex);

      cd.setProfileData(s);
      fireTableCellUpdated(rowIndex, PROFILE_DATA_COLUMN);
    }
  }
}
/**
 * Represents a panel that displays the Energy Consumption Simulation section of the Statistics Tab
 * information page.
 */
public abstract class EnergyModelStatisticsPanel extends JPanel {
  private static final long serialVersionUID = 1L;

  // Returns the font used for the header portion of the panel.
  protected static final Font HEADER_FONT = new Font("HeaderFont", Font.BOLD, 16);

  // Returns the font used for the data portion of the panel.
  protected static final Font TEXT_FONT = new Font("TEXT_FONT", Font.PLAIN, 12);

  // Returns a constant value for header data spacing.
  protected static final int HEADER_DATA_SPACING = 10;

  private JLabel gpsActiveLabel;
  private JLabel gpsActiveValueLabel;
  private JLabel gpsStandbyLabel;
  private JLabel gpsStandbyValueLabel;
  private JLabel gpsTotalLabel;
  private JLabel gpsTotalValueLabel;
  private JLabel cameraTotalLabel;
  private JLabel cameraTotalValueLabel;
  private JLabel bluetoothActiveLabel;
  private JLabel bluetoothActiveValueLabel;
  private JLabel bluetoothStandbyLabel;
  private JLabel bluetoothStandbyValueLabel;
  private JLabel bluetoothTotalLabel;
  private JLabel bluetoothTotalValueLabel;
  private JLabel screenTotalLabel;
  private JLabel screenTotalValueLabel;

  private static final ResourceBundle rb = ResourceBundleManager.getDefaultBundle();
  private static final String units = rb.getString("energy.units");

  private JPanel energyStatisticsLeftAlligmentPanel = null;
  private JPanel energyStatisticsPanel = null;
  private JLabel energyStatisticsHeaderLabel = null;
  private JPanel spacePanel = null;

  // Returns the JPanel object encapsulated by this class.
  protected JPanel energyConsumptionStatsPanel = null;

  // Returns a map of strings that contain the energy statistics column in the panel.
  protected Map<String, String> energyContent = new LinkedHashMap<String, String>();

  /** Initializes a new instance of the EnergyModelStatisticsPanel class. */
  public EnergyModelStatisticsPanel() {
    super(new BorderLayout(10, 10));
    setBackground(UIManager.getColor(AROUIManager.PAGE_BACKGROUND_KEY));
    setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
    init();
    add(energyStatisticsLeftAlligmentPanel, BorderLayout.WEST);
  }

  /**
   * Refreshes the label values in the EnergyModelStatisticsPanel using the specified trace data.
   *
   * @param analysis - The Analysis object containing the trace data.
   */
  public synchronized void refresh(TraceData.Analysis analysis) {
    energyContent.clear();

    NumberFormat nf = NumberFormat.getNumberInstance();
    nf.setMaximumFractionDigits(2);
    nf.setMinimumFractionDigits(2);
    refreshRRCStatistic(analysis, nf);
    if (analysis != null) {
      updatePeripheralStatistics(analysis, nf, units, analysis.getEnergyModel());
      updatePeripheralStatisticsValues();
    } else {
      updatePeripheralStatistics(null, null, null, null);
    }
  }

  /**
   * Returns a Map containing key-value pairs of the energy consumption statistics data.
   *
   * @return A Map object containing the energy consumption statistics data.
   */
  public Map<String, String> getEnergyContent() {
    return Collections.unmodifiableMap(energyContent);
  }

  /**
   * Refreshes the JPanel that contains the RRC portion of the Energy Consumption statistics data.
   *
   * @param analysis - The Analysis object containing the trace data.
   * @param nf - The number format used to display the label values.
   */
  protected abstract void refreshRRCStatistic(TraceData.Analysis analysis, NumberFormat nf);

  /** Creates the JPanel that contains the RRC statistics data. */
  protected abstract void createRRCStatsPanel();

  private void init() {

    energyConsumptionStatsPanel = new JPanel(new GridLayout(17, 2, 5, 5));
    energyStatisticsLeftAlligmentPanel = new JPanel(new BorderLayout());
    energyConsumptionStatsPanel.setBackground(UIManager.getColor(AROUIManager.PAGE_BACKGROUND_KEY));
    energyStatisticsLeftAlligmentPanel.setBackground(
        UIManager.getColor(AROUIManager.PAGE_BACKGROUND_KEY));

    createRRCStatsPanel();
    createPeripheralStatisticsPanel();

    energyStatisticsPanel = new JPanel();
    energyStatisticsPanel.setLayout(new VerticalLayout());
    energyStatisticsPanel.setBackground(UIManager.getColor(AROUIManager.PAGE_BACKGROUND_KEY));
    energyStatisticsHeaderLabel = new JLabel(rb.getString("energy.title"));
    energyStatisticsHeaderLabel.setFont(HEADER_FONT);
    energyStatisticsPanel.add(energyStatisticsHeaderLabel);

    spacePanel = new JPanel();
    spacePanel.setPreferredSize(new Dimension(this.getWidth(), HEADER_DATA_SPACING));
    spacePanel.setBackground(UIManager.getColor(AROUIManager.PAGE_BACKGROUND_KEY));
    energyStatisticsPanel.add(spacePanel);

    energyStatisticsPanel.add(energyConsumptionStatsPanel);

    energyStatisticsLeftAlligmentPanel.add(energyStatisticsPanel, BorderLayout.WEST);
  }

  /** Creates the JPanel that contains the peripheral statistics data. */
  private void createPeripheralStatisticsPanel() {

    gpsActiveLabel = new JLabel(rb.getString("energy.gpsActive"));
    gpsActiveLabel.setFont(TEXT_FONT);
    gpsActiveValueLabel = new JLabel();
    gpsActiveValueLabel.setFont(TEXT_FONT);
    gpsStandbyLabel = new JLabel(rb.getString("energy.gpsStandby"));
    gpsStandbyLabel.setFont(TEXT_FONT);
    gpsStandbyValueLabel = new JLabel();
    gpsStandbyValueLabel.setFont(TEXT_FONT);
    gpsTotalLabel = new JLabel(rb.getString("energy.gpsTotal"));
    gpsTotalLabel.setFont(TEXT_FONT);
    gpsTotalValueLabel = new JLabel();
    gpsTotalValueLabel.setFont(TEXT_FONT);
    cameraTotalLabel = new JLabel(rb.getString("energy.cameraTotal"));
    cameraTotalLabel.setFont(TEXT_FONT);
    cameraTotalValueLabel = new JLabel();
    cameraTotalValueLabel.setFont(TEXT_FONT);
    bluetoothActiveLabel = new JLabel(rb.getString("energy.bluetoothActive"));
    bluetoothActiveLabel.setFont(TEXT_FONT);
    bluetoothActiveValueLabel = new JLabel();
    bluetoothActiveValueLabel.setFont(TEXT_FONT);
    bluetoothStandbyLabel = new JLabel(rb.getString("energy.bluetoothStandby"));
    bluetoothStandbyLabel.setFont(TEXT_FONT);
    bluetoothStandbyValueLabel = new JLabel();
    bluetoothStandbyValueLabel.setFont(TEXT_FONT);
    bluetoothTotalLabel = new JLabel(rb.getString("energy.bluetoothTotal"));
    bluetoothTotalLabel.setFont(TEXT_FONT);
    bluetoothTotalValueLabel = new JLabel();
    bluetoothTotalValueLabel.setFont(TEXT_FONT);
    screenTotalLabel = new JLabel(rb.getString("energy.screenTotal"));
    screenTotalLabel.setFont(TEXT_FONT);
    screenTotalValueLabel = new JLabel();
    screenTotalValueLabel.setFont(TEXT_FONT);

    energyConsumptionStatsPanel.add(gpsActiveLabel);
    energyConsumptionStatsPanel.add(gpsActiveValueLabel);
    energyConsumptionStatsPanel.add(gpsStandbyLabel);
    energyConsumptionStatsPanel.add(gpsStandbyValueLabel);
    energyConsumptionStatsPanel.add(gpsTotalLabel);
    energyConsumptionStatsPanel.add(gpsTotalValueLabel);
    energyConsumptionStatsPanel.add(cameraTotalLabel);
    energyConsumptionStatsPanel.add(cameraTotalValueLabel);
    energyConsumptionStatsPanel.add(bluetoothActiveLabel);
    energyConsumptionStatsPanel.add(bluetoothActiveValueLabel);
    energyConsumptionStatsPanel.add(bluetoothStandbyLabel);
    energyConsumptionStatsPanel.add(bluetoothStandbyValueLabel);
    energyConsumptionStatsPanel.add(bluetoothTotalLabel);
    energyConsumptionStatsPanel.add(bluetoothTotalValueLabel);
    energyConsumptionStatsPanel.add(screenTotalLabel);
    energyConsumptionStatsPanel.add(screenTotalValueLabel);
  }

  /**
   * Updates the JPanel that contains the Energy Consumption statistics data.
   *
   * @param TraceData .Analysis analysis data
   * @param NumberFormat The display format
   * @param String The units for energy
   * @param EnergyModel The energy model
   */
  private void updatePeripheralStatistics(
      TraceData.Analysis analysis, NumberFormat nf, String units, EnergyModel model) {
    if (analysis != null) {
      gpsActiveValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getGpsActiveEnergy())));
      gpsStandbyValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getGpsStandbyEnergy())));
      gpsTotalValueLabel.setText(MessageFormat.format(units, nf.format(model.getTotalGpsEnergy())));
      cameraTotalValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getTotalCameraEnergy())));
      bluetoothActiveValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getBluetoothActiveEnergy())));
      bluetoothStandbyValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getBluetoothStandbyEnergy())));
      bluetoothTotalValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getTotalBluetoothEnergy())));
      screenTotalValueLabel.setText(
          MessageFormat.format(units, nf.format(model.getTotalScreenEnergy())));
    } else {
      gpsActiveValueLabel.setText(null);
      gpsStandbyValueLabel.setText(null);
      gpsTotalValueLabel.setText(null);
      cameraTotalValueLabel.setText(null);
      bluetoothActiveValueLabel.setText(null);
      bluetoothStandbyValueLabel.setText(null);
      bluetoothTotalValueLabel.setText(null);
      screenTotalValueLabel.setText(null);
    }
  }

  /** Updates the JPanel that contains the Energy Consumption statistics data with values. */
  private void updatePeripheralStatisticsValues() {
    energyContent.put(rb.getString("energy.gpsActive"), gpsActiveValueLabel.getText());
    energyContent.put(rb.getString("energy.gpsStandby"), gpsStandbyValueLabel.getText());
    energyContent.put(rb.getString("energy.gpsTotal"), gpsTotalValueLabel.getText());
    energyContent.put(rb.getString("energy.cameraTotal"), cameraTotalValueLabel.getText());
    energyContent.put(rb.getString("energy.bluetoothActive"), bluetoothActiveValueLabel.getText());
    energyContent.put(
        rb.getString("energy.bluetoothStandby"), bluetoothStandbyValueLabel.getText());
    energyContent.put(rb.getString("energy.bluetoothTotal"), bluetoothTotalValueLabel.getText());
    energyContent.put(rb.getString("energy.screenTotal"), screenTotalValueLabel.getText());
  }

  /**
   * Method to add the energy statistics content in the csv file
   *
   * @throws IOException
   */
  public FileWriter addEnergyContent(FileWriter writer) throws IOException {
    final String lineSep = System.getProperty(rb.getString("statics.csvLine.seperator"));
    for (Map.Entry<String, String> iter : energyContent.entrySet()) {
      String individualVal = iter.getValue().replace(rb.getString("statics.csvCell.seperator"), "");
      writer.append(iter.getKey());
      writer.append(rb.getString("statics.csvCell.seperator"));
      if (individualVal.contains(rb.getString("statics.csvUnits.j"))) {
        writer.append(
            individualVal.substring(0, individualVal.indexOf(rb.getString("statics.csvUnits.j"))));
        writer.append(rb.getString("statics.csvCell.seperator"));
        writer.append(rb.getString("statics.csvUnits.j"));
      } else {
        writer.append(individualVal);
      }
      writer.append(lineSep);
    }
    return writer;
  }
} // @jve:decl-index=0:visual-constraint="10,10"
 @Override
 protected void setUp() throws Exception {
   super.setUp();
   ResourceBundleManager.getInstance(getProject()).loadState(new ResourceBundleManagerState());
 }
/** Represents the Diagnostic tab screen. */
public class AROAdvancedTabb extends JPanel {

  private static final long serialVersionUID = 1L;

  private static final ResourceBundle rb = ResourceBundleManager.getDefaultBundle();

  private static final int MAX_ZOOM = 4;
  private static final Double matchingSecondsRange = 0.5;

  // Split pane for TCP flow data
  private JSplitPane internalPanel;

  // TCP Flows header
  private JPanel tcpFlowsHeadingPanel;
  private JLabel tcpFlowsLabel;

  // Components for TCP Flows scroll table
  private JPanel jTCPFlowsPanel;
  private JScrollPane jTCPFlowsScrollPane;
  private TCPFlowsTableModel jTCPFlowsTableModel = new TCPFlowsTableModel();
  private DataTable<TCPSession> jTCPFlowsTable;

  // TCP flow detail tabbed pane
  private JTabbedPane jTCPFlowsContentTabbedPane;

  private RequestResponseDetailsPanel jHttpReqResPanel;

  // Packet view
  private JScrollPane jPacketViewTapScrollPane;

  private PacketInfoTableModel jPacketViewTableModel = new PacketInfoTableModel();
  private DataTable<PacketInfo> jPacketViewTable;

  // Content view
  private JScrollPane jContentViewScrollPane; // Content View
  private JTextArea jContentTextArea; // Context text

  // network profile panel
  private DeviceNetworkProfilePanel deviceNetworkProfilePanel;

  // Chart panel
  private GraphPanel graphPanel;

  private AROVideoPlayer aroVideoPlayer;

  // Trace data currently displayed
  private TraceData.Analysis analysisData;

  /** Initializes a new instance of the AROAdvancedTabb class. */
  public AROAdvancedTabb() {
    this.setLayout(new BorderLayout());
    // Add profile panel
    this.add(getDeviceNetworkProfilePanel(), BorderLayout.NORTH);
    JPanel chartAndTablePanel = new JPanel();
    chartAndTablePanel.setLayout(new BorderLayout());
    // Add chart
    chartAndTablePanel.add(getGraphPanel(), BorderLayout.NORTH);
    // Add TCP flows split pane
    chartAndTablePanel.add(getOrientationPanel(), BorderLayout.CENTER);
    this.add(chartAndTablePanel, BorderLayout.CENTER);
  }

  /**
   * Sets the trace data to be displayed on the Diagnostic tab screen.
   *
   * @param analysisData The trace analysis data to be displayed.
   */
  public synchronized void setAnalysisData(TraceData.Analysis analysisData) {
    this.analysisData = analysisData;
    if (analysisData != null) {
      jTCPFlowsTableModel.setData(analysisData.getTcpSessions());
    } else {
      jTCPFlowsTableModel.setData(null);
    }
    getGraphPanel().resetChart(analysisData);
    deviceNetworkProfilePanel.refresh(analysisData);
  }

  /**
   * Sets the video player to be used with this AROAdvancedTabb. The video player displays a video
   * of screen captures that were recorded while trace data was being captured. The current time
   * position in the video playback is updated to match the selected time position in the
   * AROAdvancedTabb chart.
   *
   * @param videoPlayer An AROVideoPlayer object representing the video player to be used with this
   *     AROAdvancedTabb.
   */
  public void setVideoPlayer(AROVideoPlayer videoPlayer) {
    aroVideoPlayer = videoPlayer;
  }

  /**
   * Sets the chart options in the AROAdvancedTab to the specified List of ChartPlotOptions.
   *
   * @param optionsSelected A List containing the chart plot options. Typically, these are the
   *     options selected using the ChartPlotOptions dialog in the View menu.
   */
  public void setChartOptions(List<ChartPlotOptions> optionsSelected) {
    this.getGraphPanel().setChartOptions(optionsSelected);
  }

  private JSplitPane getOrientationPanel() {
    if (internalPanel == null) {
      internalPanel =
          new JSplitPane(
              JSplitPane.VERTICAL_SPLIT, getJTCPFlowsPanel(), getJTCPFlowsContentTabbedPane());
      internalPanel.setResizeWeight(.5);
      internalPanel.updateUI();
    }
    return internalPanel;
  }

  /** Initializes and returns the Device network profile panel. */
  private DeviceNetworkProfilePanel getDeviceNetworkProfilePanel() {
    if (deviceNetworkProfilePanel == null) {
      deviceNetworkProfilePanel = new DeviceNetworkProfilePanel();
    }
    return deviceNetworkProfilePanel;
  }

  /** Returns the Panel that contains the graph. */
  private GraphPanel getGraphPanel() {
    if (this.graphPanel == null) {
      this.graphPanel = new GraphPanel();
      graphPanel.setZoomFactor(2);
      graphPanel.setMaxZoom(MAX_ZOOM);
      graphPanel.addGraphPanelListener(
          new GraphPanelListener() {

            @Override
            public void graphPanelClicked(double timeStamp) {
              setTimeLineLinkedComponents(timeStamp, matchingSecondsRange);
              if (aroVideoPlayer != null) {
                aroVideoPlayer.setMediaDisplayTime(timeStamp);
              }
            }
          });
    }
    return this.graphPanel;
  }

  /**
   * Returns the video player associated with this instance.
   *
   * @return An AROVideoPlayer object.
   */
  public AROVideoPlayer getVideoPlayer() {
    return aroVideoPlayer;
  }

  /** Initializes and returns the Tabbed pane at the bottom. */
  private JTabbedPane getJTCPFlowsContentTabbedPane() {
    if (jTCPFlowsContentTabbedPane == null) {
      jTCPFlowsContentTabbedPane = new JTabbedPane();
      jTCPFlowsContentTabbedPane.addTab(
          rb.getString("tcp.tab.reqResp"), null, getJHttpReqResPanel(), null);
      jTCPFlowsContentTabbedPane.addTab(
          rb.getString("tcp.tab.packet"), null, getJPacketViewTapScrollPane(), null);
      jTCPFlowsContentTabbedPane.addTab(
          rb.getString("tcp.tab.content"), null, getJContentViewScrollPane(), null);
      jTCPFlowsContentTabbedPane.addChangeListener(
          new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
              if (jTCPFlowsContentTabbedPane.getSelectedComponent()
                  == getJContentViewScrollPane()) {
                TCPSession sess = jTCPFlowsTable.getSelectedItem();
                if (sess != null) {
                  jContentTextArea.setText(sess.getDataText());
                  jContentTextArea.setCaretPosition(0);
                } else {
                  jContentTextArea.setText(null);
                }
              }
            }
          });
    }
    return jTCPFlowsContentTabbedPane;
  }

  /** @return the jHttpReqResPanel */
  private RequestResponseDetailsPanel getJHttpReqResPanel() {
    if (jHttpReqResPanel == null) {
      jHttpReqResPanel = new RequestResponseDetailsPanel();
    }
    return jHttpReqResPanel;
  }

  /**
   * Initializes jTCPFlowsPanel
   *
   * @return javax.swing.JPanel
   */
  private JPanel getJTCPFlowsPanel() {
    if (jTCPFlowsPanel == null) {
      jTCPFlowsPanel = new JPanel();
      jTCPFlowsPanel.setPreferredSize(new Dimension(400, 160));
      jTCPFlowsPanel.setLayout(new BorderLayout());
      jTCPFlowsPanel.add(getTcpFlowsHeadingPanel(), BorderLayout.NORTH);
      jTCPFlowsPanel.add(getJTCPFlowsScrollPane(), BorderLayout.CENTER);
    }
    return jTCPFlowsPanel;
  }

  /** Initializes and returns the PacketViewTapScrollPane */
  private JScrollPane getJPacketViewTapScrollPane() {
    if (jPacketViewTapScrollPane == null) {
      jPacketViewTapScrollPane = new JScrollPane(getJPacketViewTable());
    }
    return jPacketViewTapScrollPane;
  }

  /** Returns the DataTable for the packet view. */
  private DataTable<PacketInfo> getJPacketViewTableAsDataTable() {
    return jPacketViewTable;
  }

  /** Initializes and returns the Packet View Table. */
  private JTable getJPacketViewTable() {
    if (jPacketViewTable == null) {
      jPacketViewTable = new DataTable<PacketInfo>(jPacketViewTableModel);
      jPacketViewTable.setAutoCreateRowSorter(true);
      jPacketViewTable.setGridColor(Color.LIGHT_GRAY);
      jPacketViewTable
          .getSelectionModel()
          .addListSelectionListener(
              new ListSelectionListener() {
                PacketInfo packetInfo;

                @Override
                public synchronized void valueChanged(ListSelectionEvent arg0) {
                  PacketInfo packetInfo = jPacketViewTable.getSelectedItem();
                  if (packetInfo != null && packetInfo != this.packetInfo) {
                    double crossHairValue = packetInfo.getTimeStamp();
                    boolean centerGraph =
                        !(crossHairValue <= graphPanel.getViewportUpperBound()
                            && crossHairValue >= graphPanel.getViewportLowerBound());
                    graphPanel.setGraphView(crossHairValue, centerGraph);
                    getJHttpReqResPanel().select(packetInfo.getRequestResponseInfo());
                    if (aroVideoPlayer != null) {
                      aroVideoPlayer.setMediaDisplayTime(graphPanel.getCrosshair());
                    }
                  }
                  this.packetInfo = packetInfo;
                }
              });
    }
    return jPacketViewTable;
  }

  /** Initializes and returns the Scroll Pane for the Content View tab at the bottom. */
  private JScrollPane getJContentViewScrollPane() {
    if (jContentViewScrollPane == null) {
      if (jContentTextArea == null) {
        jContentTextArea = new JTextArea(10, 20);
      }
      jContentViewScrollPane = new JScrollPane(jContentTextArea);
      jContentTextArea.setLineWrap(true);
      jContentTextArea.setCaretPosition(0);
      jContentViewScrollPane.setPreferredSize(new Dimension(100, 200));
    }
    return jContentViewScrollPane;
  }

  /** Initializes and returns the TCPFlowsScrollPane. */
  private JScrollPane getJTCPFlowsScrollPane() {
    if (jTCPFlowsScrollPane == null) {
      jTCPFlowsScrollPane = new JScrollPane(getJTCPFlowsTable());
      jTCPFlowsScrollPane.setPreferredSize(new Dimension(100, 200));
    }
    return jTCPFlowsScrollPane;
  }

  /** Initializes and returns the Scroll Pane for the TCP flows table. */
  private DataTable<TCPSession> getJTCPFlowsTable() {
    if (jTCPFlowsTable == null) {
      jTCPFlowsTable = new DataTable<TCPSession>(jTCPFlowsTableModel);
      jTCPFlowsTable.setAutoCreateRowSorter(true);
      jTCPFlowsTable.setGridColor(Color.LIGHT_GRAY);
      jTCPFlowsTable
          .getSelectionModel()
          .addListSelectionListener(
              new ListSelectionListener() {
                private TCPSession tcp;

                @Override
                public synchronized void valueChanged(ListSelectionEvent arg0) {
                  TCPSession tcp = jTCPFlowsTable.getSelectedItem();
                  if (tcp != this.tcp) {
                    if (tcp != null) {
                      jPacketViewTableModel.setData(tcp.getPackets());
                      jPacketViewTable.setGridColor(Color.LIGHT_GRAY);
                      if (!tcp.getPackets().isEmpty()) {
                        jPacketViewTable.getSelectionModel().setSelectionInterval(0, 0);
                      }
                      if (jTCPFlowsContentTabbedPane.getSelectedComponent()
                          == getJContentViewScrollPane()) {
                        jContentTextArea.setText(tcp.getDataText());
                      }
                      jContentTextArea.setCaretPosition(0);
                      getJHttpReqResPanel().setData(tcp.getRequestResponseInfo());
                    } else {
                      jPacketViewTableModel.removeAllRows();
                      getJHttpReqResPanel().setData(null);
                      jContentTextArea.setText(null);
                    }
                    this.tcp = tcp;
                  }
                }
              });
    }
    return jTCPFlowsTable;
  }

  /** Creates the TCP Flows heading panel. */
  private JPanel getTcpFlowsHeadingPanel() {
    if (tcpFlowsHeadingPanel == null) {
      tcpFlowsHeadingPanel = new JPanel();
      tcpFlowsHeadingPanel.setLayout(new GridBagLayout());
      tcpFlowsHeadingPanel.add(getTcpFlowsLabel());
      tcpFlowsHeadingPanel.setPreferredSize(new Dimension(110, 20));
    }
    return tcpFlowsHeadingPanel;
  }

  /** Returns the TCP flows label. */
  private JLabel getTcpFlowsLabel() {
    if (tcpFlowsLabel == null) {
      tcpFlowsLabel = new JLabel(rb.getString("tcp.title"));
    }
    return tcpFlowsLabel;
  }

  /**
   * Sets the chart cross hair to the specified timestamp in the chart.
   *
   * @param timeStamp - The timestamp in the chart to which the cross hair should be set.
   */
  public synchronized void setTimeLineLinkedComponents(double timeStamp) {
    if (analysisData != null) {
      if (timeStamp < 0.0) {
        timeStamp = 0.0;
      }
      if (timeStamp > analysisData.getTraceData().getTraceDuration()) {
        timeStamp = analysisData.getTraceData().getTraceDuration();
      }
      getGraphPanel().setGraphView(timeStamp);
    }
  }

  /** Method to set the time on graph panel. */
  private synchronized void setTimeLineLinkedComponents(
      double timeStamp, double dTimeRangeInterval) {

    if (analysisData != null) {
      boolean bTCPTimeStampFound = false;
      boolean bExactMatch = false;

      // Do exact match of dTimeInterval == 0.0;
      // If dTimeInterval < 0.0, don't try to match up with the TCP_Flow
      // or packets when click comes from graph or video
      if (dTimeRangeInterval == 0.0) {
        bExactMatch = true;
      } else if (dTimeRangeInterval < 0.0) {
        repaint();
        return;
      }

      // Attempt to find corresponding packet for time.
      double packetTimeStamp = 0.0;
      double packetTimeStampDiff = 0.0;
      double previousPacketTimeStampDiff = 9999.0;
      TCPSession bestMatchingTcpSession = null;
      PacketInfo bestMatchingPacketInfo = null;
      for (TCPSession tcpSess : analysisData.getTcpSessions()) {
        PacketInfo packetInfo =
            getBestMatchingPacketInTcpSession(tcpSess, bExactMatch, timeStamp, dTimeRangeInterval);
        if (packetInfo != null) {
          packetTimeStamp = packetInfo.getTimeStamp();
          packetTimeStampDiff = timeStamp - packetTimeStamp;
          if (packetTimeStampDiff < 0.0) {
            packetTimeStampDiff *= -1.0;
          }
          if (packetTimeStampDiff < previousPacketTimeStampDiff) {
            bestMatchingTcpSession = tcpSess;
            bestMatchingPacketInfo = packetInfo;
            bTCPTimeStampFound = true;
          }
        }
      }

      if (bTCPTimeStampFound) {
        getJTCPFlowsTable().selectItem(bestMatchingTcpSession);
        jPacketViewTable.selectItem(bestMatchingPacketInfo);
        jPacketViewTable.setGridColor(Color.LIGHT_GRAY);
        if (bestMatchingPacketInfo != null) {
          jHttpReqResPanel.select(bestMatchingPacketInfo.getRequestResponseInfo());
        } else {
          jHttpReqResPanel.select(null);
        }
      } else {
        getJTCPFlowsTable().selectItem(null);
        jPacketViewTable.selectItem(null);
        jHttpReqResPanel.select(null);
        if (aroVideoPlayer != null) {
          aroVideoPlayer.setMediaDisplayTime(graphPanel.getCrosshair());
        }
      }
    }
  }

  /** Provides the Best matching packet info from the provided tcp session. */
  private PacketInfo getBestMatchingPacketInTcpSession(
      TCPSession tcpSession, boolean bExactMatch, double timeStamp, double dTimeRangeInterval) {

    // Try to eliminate session before iterating through packets
    if (tcpSession.getSessionStartTime() > timeStamp
        || tcpSession.getSessionEndTime() < timeStamp) {
      return null;
    }

    double packetTimeStamp = 0.0;
    PacketInfo matchedPacket = null;
    for (PacketInfo p : tcpSession.getPackets()) {
      packetTimeStamp = p.getTimeStamp();
      if ((bExactMatch && (packetTimeStamp == timeStamp))
          || ((packetTimeStamp >= (timeStamp - dTimeRangeInterval))
              && (packetTimeStamp <= (timeStamp + dTimeRangeInterval)))) {
        matchedPacket = p;
      }
    }
    return matchedPacket;
  }

  /**
   * Highlights the specified TCP session in the TCP flows table.
   *
   * @param tcpSession - The TCPSession object to be highlighted.
   */
  public void setHighlightedTCP(TCPSession tcpSession) {
    getJTCPFlowsTable().selectItem(tcpSession);
  }

  /**
   * Highlights the specified packet in the Packet view table.
   *
   * @param packetInfo The PacketInfo object representing the packet to be highlighted.
   */
  public void setHighlightedPacketView(PacketInfo packetInfo) {
    if (packetInfo.getSession() != null) {
      setHighlightedTCP(packetInfo.getSession());
      getJPacketViewTableAsDataTable().selectItem(packetInfo);
    }
  }

  /**
   * Selects the specified request/response object in the request/response list
   *
   * @param rr - The HttpRequestResponseInfo object to be selected in the list.
   */
  public void setHighlightedRequestResponse(HttpRequestResponseInfo rr) {
    if (rr != null) {
      setHighlightedTCP(rr.getSession());
      getJTCPFlowsContentTabbedPane().setSelectedComponent(getJHttpReqResPanel());
    }
    getJHttpReqResPanel().setHighlightedRequestResponse(rr);
  }

  /** Resets the size of any panes that have been split so that they are of equal size. */
  public void resetSplitPanesAdvancedTabb() {
    internalPanel.setDividerLocation(0.5);
  }

  /**
   * Returns the currently displayed graph panel.
   *
   * @return An object containing the currently displayed graph panel.
   */
  public GraphPanel getDisplayedGraphPanel() {
    return this.graphPanel;
  }
}