<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/core/kernels/data/experimental/sampling_dataset_op.h"

#include "tensorflow/core/kernels/data/dataset_test_base.h"

namespace tensorflow {
namespace data {
namespace experimental {
namespace {

constexpr char kNodeName[] = "sampling_dataset";
constexpr char kIteratorPrefix[] = "Iterator";
constexpr int64 kRandomSeed = 42;
constexpr int64 kRandomSeed2 = 7;
constexpr int64 kStart = 0;
constexpr int64 kStep = 1;

class SamplingDatasetParams : public DatasetParams {
 public:
  SamplingDatasetParams(float rate, int64 num_elements,
                        DataTypeVector output_dtypes,
                        std::vector<PartialTensorShape> output_shapes,
                        string node_name)
      : DatasetParams(std::move(output_dtypes), std::move(output_shapes),
                      std::move(node_name)),
        rate(CreateTensor<float>(TensorShape({}), {rate})),
        range_dataset_params(kStart, num_elements, kStep, {DT_INT64},
                             {PartialTensorShape({})}, "") {}

  Status MakeInputs(gtl::InlinedVector<TensorValue, 4>* inputs) override {
    if (input_dataset.NumElements() == 0 ||
        input_dataset.dtype() != DT_VARIANT) {
      return tensorflow::errors::Internal(
          "The input dataset is not populated as the dataset tensor yet.");
    }
    *inputs = {TensorValue(&input_dataset), TensorValue(&rate),
               TensorValue(&seed_tensor_), TensorValue(&seed2_tensor_)};
    return Status::OK();
  }

  // Target sample rate, range (0,1], wrapped in a scalar Tensor
  Tensor rate;

  // Parameters of the sequence of numbers that will serve as the dynamic input
  // of the kernel.
  RangeDatasetParams range_dataset_params;

  // RangeDataset kernel wrapped in a variant tensor. Initialized by the test
  // harness class because the MakeRangeDataset() method requires an instance of
  // DatasetOpsTestBase.
  Tensor input_dataset;

 private:
  // Boxed versions of kRandomSeed and kRandomSeed2.
  Tensor seed_tensor_ = CreateTensor<int64>(TensorShape({}), {kRandomSeed});
  Tensor seed2_tensor_ = CreateTensor<int64>(TensorShape({}), {kRandomSeed2});
};

class SamplingDatasetOpTest
    : public DatasetOpsTestBaseV2<SamplingDatasetParams> {
 public:
  Status Initialize(SamplingDatasetParams* dataset_params) override {
    // Step 1: Set up enough of a TF runtime to be able to invoke a kernel.
    TF_RETURN_IF_ERROR(InitThreadPool(thread_num_));
    TF_RETURN_IF_ERROR(InitFunctionLibraryRuntime({}, cpu_num_));

    // Step 2: Create the dataset that will provide input data for the kernel
    TF_RETURN_IF_ERROR(MakeRangeDataset(dataset_params->range_dataset_params,
                                        &dataset_params->input_dataset));

    // Step 3: Box up the four inputs to the kernel inside TensorValue objects
    // inside a vector.
    gtl::InlinedVector<TensorValue, 4> inputs;
    TF_RETURN_IF_ERROR(dataset_params->MakeInputs(&inputs));

    // Step 4: Create a dataset kernel to test, passing in attributes of the
    // kernel.
    TF_RETURN_IF_ERROR(
        CreateSamplingDatasetOpKernel(*dataset_params, &dataset_kernel_));

    // Step 5: Create a context in which the kernel will operate. This is where
    // the kernel gets initialized with its inputs
    TF_RETURN_IF_ERROR(
        CreateDatasetContext(dataset_kernel_.get(), &inputs, &dataset_ctx_));

    // Step 6: Unbox the DatasetBase object inside the variant tensor backing
    // the kernel.
    TF_RETURN_IF_ERROR(
        CreateDataset(dataset_kernel_.get(), dataset_ctx_.get(), &dataset_));

    // Step 7: Create an iterator in case the test needs to read the output of
    // the dataset.
    TF_RETURN_IF_ERROR(
        CreateIteratorContext(dataset_ctx_.get(), &iterator_ctx_));
    TF_RETURN_IF_ERROR(dataset_->MakeIterator(iterator_ctx_.get(),
                                              kIteratorPrefix, &iterator_));

    return Status::OK();
  }

 protected:
  // Creates a new `SamplingDataset` op kernel.
  // Doesn't initialize the kernel's static parameters because they are inputs,
  // not attributes.
  Status CreateSamplingDatasetOpKernel(
      const SamplingDatasetParams& dataset_params,
      std::unique_ptr<OpKernel>* sampling_dataset_op_kernel) {
    NodeDef node_def = test::function::NDef(
        kNodeName, name_utils::OpName(SamplingDatasetOp::kDatasetType),
        // Inputs
        {SamplingDatasetOp::kInputDataset, SamplingDatasetOp::kRate,
         SamplingDatasetOp::kSeed, SamplingDatasetOp::kSeed2},
        // Attributes
        {{SamplingDatasetOp::kOutputTypes, dataset_params.output_dtypes},
         {SamplingDatasetOp::kOutputShapes, dataset_params.output_shapes}});
    TF_RETURN_IF_ERROR(CreateOpKernel(node_def, sampling_dataset_op_kernel));
    return Status::OK();
  }
};

SamplingDatasetParams OneHundredPercentSampleParams() {
  return {/*rate*/ 1.0,
          /*num_elements*/ 3,
          /*output_dtypes*/ {DT_INT64},
          /*output_shapes*/ {PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

SamplingDatasetParams TenPercentSampleParams() {
  return {/*rate*/ 0.1,
          /*num_elements*/ 20,
          /*output_dtypes*/ {DT_INT64},
          /*output_shapes*/ {PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

SamplingDatasetParams ZeroPercentSampleParams() {
  return {/*rate*/ 0.0,
          /*num_elements*/ 20,
          /*output_dtypes*/ {DT_INT64},
          /*output_shapes*/ {PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

class ParameterizedGetNextTest : public SamplingDatasetOpTest,
                                 public ::testing::WithParamInterface<
                                     GetNextTestCase<SamplingDatasetParams>> {};

std::vector<GetNextTestCase<SamplingDatasetParams>> GetNextTestCases() {
  return {
      // Test case 1: 100% sample should return all inputs
      {/*dataset_params=*/OneHundredPercentSampleParams(),
       /*expected_outputs=*/CreateTensors<int64>(TensorShape({}),
                                                 {{0}, {1}, {2}})},

      // Test case 2: 10% sample should return about 10% of inputs, and the
      // specific inputs returned shouldn't change across build environments.
      {/*dataset_params=*/TenPercentSampleParams(),
       /*expected_outputs=*/CreateTensors<int64>(TensorShape({}),
                                                 {{9}, {11}, {19}})},

      // Test case 3: 0% sample should return nothing and should not crash.
      {/*dataset_params=*/ZeroPercentSampleParams(), /*expected_outputs=*/{}}};
}

TEST_P(ParameterizedGetNextTest, GetNext) {
  auto test_case = GetParam();
  TF_ASSERT_OK(Initialize(&test_case.dataset_params));
  TF_ASSERT_OK(
      CheckIteratorGetNext(test_case.expected_outputs, /*compare_order=*/true));
}

INSTANTIATE_TEST_SUITE_P(
    SamplingDatasetOpTest, ParameterizedGetNextTest,
    ::testing::ValuesIn(std::vector<GetNextTestCase<SamplingDatasetParams>>(
        GetNextTestCases())));

TEST_F(SamplingDatasetOpTest, DatasetNodeName) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckDatasetNodeName(dataset_params.node_name));
}

TEST_F(SamplingDatasetOpTest, DatasetTypeString) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckDatasetTypeString(
      name_utils::OpName(SamplingDatasetOp::kDatasetType)));
}

TEST_F(SamplingDatasetOpTest, DatasetOutputDtypes) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckDatasetOutputDtypes({DT_INT64}));
}

TEST_F(SamplingDatasetOpTest, DatasetOutputShapes) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckDatasetOutputShapes({PartialTensorShape({})}));
}

class ParameterizedCardinalityTest
    : public SamplingDatasetOpTest,
      public ::testing::WithParamInterface<
          CardinalityTestCase<SamplingDatasetParams>> {};

std::vector<CardinalityTestCase<SamplingDatasetParams>> CardinalityTestCases() {
  return {{/*dataset_params=*/OneHundredPercentSampleParams(),
           /*expected_cardinality=*/kUnknownCardinality},
          {/*dataset_params=*/TenPercentSampleParams(),
           /*expected,cardinality=*/kUnknownCardinality},
          {/*dataset_params=*/ZeroPercentSampleParams(),
           /*expected_cardinality=*/kUnknownCardinality}};
}

TEST_P(ParameterizedCardinalityTest, Cardinality) {
  auto test_case = GetParam();
  TF_ASSERT_OK(Initialize(&test_case.dataset_params));
  TF_ASSERT_OK(CheckDatasetCardinality(test_case.expected_cardinality));
}

INSTANTIATE_TEST_SUITE_P(
    SamplingDatasetOpTest, ParameterizedCardinalityTest,
    ::testing::ValuesIn(std::vector<CardinalityTestCase<SamplingDatasetParams>>(
        CardinalityTestCases())));

TEST_F(SamplingDatasetOpTest, IteratorOutputDtypes) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckIteratorOutputDtypes({DT_INT64}));
}

TEST_F(SamplingDatasetOpTest, IteratorOutputShapes) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckIteratorOutputShapes({PartialTensorShape({})}));
}

TEST_F(SamplingDatasetOpTest, IteratorOutputPrefix) {
  auto dataset_params = TenPercentSampleParams();
  TF_ASSERT_OK(Initialize(&dataset_params));
  TF_ASSERT_OK(CheckIteratorPrefix(name_utils::IteratorPrefix(
      SamplingDatasetOp::kDatasetType, kIteratorPrefix)));
}

class ParameterizedIteratorSaveAndRestoreTest
    : public SamplingDatasetOpTest,
      public ::testing::WithParamInterface<
          IteratorSaveAndRestoreTestCase<SamplingDatasetParams>> {};

std::vector<IteratorSaveAndRestoreTestCase<SamplingDatasetParams>>
IteratorSaveAndRestoreTestCases() {
  return {{/*dataset_params=*/OneHundredPercentSampleParams(),
           /*breakpoints=*/{0, 2, 5},
           /*expected_outputs=*/
           CreateTensors<int64>(TensorShape({}), {{0}, {1}, {2}})},
          {/*dataset_params=*/TenPercentSampleParams(),
           /*breakpoints=*/{0, 2, 5},
           /*expected_outputs=*/
           CreateTensors<int64>(TensorShape({}), {{9}, {11}, {19}})},
          {/*dataset_params=*/ZeroPercentSampleParams(),
           /*breakpoints=*/{0, 2, 5},
           /*expected_outputs=*/{}}};
}

TEST_P(ParameterizedIteratorSaveAndRestoreTest, IteratorSaveAndRestore) {
  auto test_case = GetParam();
  TF_ASSERT_OK(Initialize(&test_case.dataset_params));
  TF_ASSERT_OK(CheckIteratorSaveAndRestore(
      kIteratorPrefix, test_case.expected_outputs, test_case.breakpoints));
}

INSTANTIATE_TEST_SUITE_P(
    SamplingDatasetOpTest, ParameterizedIteratorSaveAndRestoreTest,
    ::testing::ValuesIn(
        std::vector<IteratorSaveAndRestoreTestCase<SamplingDatasetParams>>(
            IteratorSaveAndRestoreTestCases())));

}  // namespace
}  // namespace experimental
}  // namespace data
}  // namespace tensorflow
<commit_msg>Update test case to new format<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/core/kernels/data/experimental/sampling_dataset_op.h"

#include "tensorflow/core/kernels/data/dataset_test_base.h"

namespace tensorflow {
namespace data {
namespace experimental {
namespace {

constexpr char kNodeName[] = "sampling_dataset";
constexpr char kIteratorPrefix[] = "Iterator";
constexpr int64 kRandomSeed = 42;
constexpr int64 kRandomSeed2 = 7;
constexpr int64 kStart = 0;
constexpr int64 kStep = 1;

class SamplingDatasetParams : public DatasetParams {
 public:
  SamplingDatasetParams(float rate, int64 num_elements,
                        DataTypeVector output_dtypes,
                        std::vector<PartialTensorShape> output_shapes,
                        string node_name)
      : DatasetParams(std::move(output_dtypes), std::move(output_shapes),
                      std::move(node_name)),
        rate(CreateTensor<float>(TensorShape({}), {rate})),
        range_dataset_params(kStart, num_elements, kStep, {DT_INT64},
                             {PartialTensorShape({})}, "") {}

  Status MakeInputs(gtl::InlinedVector<TensorValue, 4>* inputs) override {
    if (input_dataset.NumElements() == 0 ||
        input_dataset.dtype() != DT_VARIANT) {
      return tensorflow::errors::Internal(
          "The input dataset is not populated as the dataset tensor yet.");
    }
    *inputs = {TensorValue(&input_dataset), TensorValue(&rate),
               TensorValue(&seed_tensor_), TensorValue(&seed2_tensor_)};
    return Status::OK();
  }

  // Target sample rate, range (0,1], wrapped in a scalar Tensor
  Tensor rate;

  // Parameters of the sequence of numbers that will serve as the dynamic input
  // of the kernel.
  RangeDatasetParams range_dataset_params;

  // RangeDataset kernel wrapped in a variant tensor. Initialized by the test
  // harness class because the MakeRangeDataset() method requires an instance of
  // DatasetOpsTestBase.
  Tensor input_dataset;

 private:
  // Boxed versions of kRandomSeed and kRandomSeed2.
  Tensor seed_tensor_ = CreateTensor<int64>(TensorShape({}), {kRandomSeed});
  Tensor seed2_tensor_ = CreateTensor<int64>(TensorShape({}), {kRandomSeed2});
};

class SamplingDatasetOpTest
    : public DatasetOpsTestBaseV2<SamplingDatasetParams> {
 public:
  Status Initialize(SamplingDatasetParams* dataset_params) override {
    // Step 1: Set up enough of a TF runtime to be able to invoke a kernel.
    TF_RETURN_IF_ERROR(InitThreadPool(thread_num_));
    TF_RETURN_IF_ERROR(InitFunctionLibraryRuntime({}, cpu_num_));

    // Step 2: Create the dataset that will provide input data for the kernel
    TF_RETURN_IF_ERROR(MakeRangeDataset(dataset_params->range_dataset_params,
                                        &dataset_params->input_dataset));

    // Step 3: Box up the four inputs to the kernel inside TensorValue objects
    // inside a vector.
    gtl::InlinedVector<TensorValue, 4> inputs;
    TF_RETURN_IF_ERROR(dataset_params->MakeInputs(&inputs));

    // Step 4: Create a dataset kernel to test, passing in attributes of the
    // kernel.
    TF_RETURN_IF_ERROR(MakeDatasetOpKernel(*dataset_params, &dataset_kernel_));

    // Step 5: Create a context in which the kernel will operate. This is where
    // the kernel gets initialized with its inputs
    TF_RETURN_IF_ERROR(
        CreateDatasetContext(dataset_kernel_.get(), &inputs, &dataset_ctx_));

    // Step 6: Unbox the DatasetBase object inside the variant tensor backing
    // the kernel.
    TF_RETURN_IF_ERROR(
        CreateDataset(dataset_kernel_.get(), dataset_ctx_.get(), &dataset_));

    // Step 7: Create an iterator in case the test needs to read the output of
    // the dataset.
    TF_RETURN_IF_ERROR(
        CreateIteratorContext(dataset_ctx_.get(), &iterator_ctx_));
    TF_RETURN_IF_ERROR(dataset_->MakeIterator(iterator_ctx_.get(),
                                              kIteratorPrefix, &iterator_));

    return Status::OK();
  }

  // Creates a new `SamplingDataset` op kernel.
  // Doesn't initialize the kernel's static parameters because they are inputs,
  // not attributes.
  Status MakeDatasetOpKernel(
      const SamplingDatasetParams& dataset_params,
      std::unique_ptr<OpKernel>* sampling_dataset_op_kernel) override {
    NodeDef node_def = test::function::NDef(
        kNodeName, name_utils::OpName(SamplingDatasetOp::kDatasetType),
        // Inputs
        {SamplingDatasetOp::kInputDataset, SamplingDatasetOp::kRate,
         SamplingDatasetOp::kSeed, SamplingDatasetOp::kSeed2},
        // Attributes
        {{SamplingDatasetOp::kOutputTypes, dataset_params.output_dtypes},
         {SamplingDatasetOp::kOutputShapes, dataset_params.output_shapes}});
    TF_RETURN_IF_ERROR(CreateOpKernel(node_def, sampling_dataset_op_kernel));
    return Status::OK();
  }
};

SamplingDatasetParams OneHundredPercentSampleParams() {
  return {/*rate*/ 1.0,
          /*num_elements*/ 3,
          /*output_dtypes*/ {DT_INT64},
          /*output_shapes*/ {PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

SamplingDatasetParams TenPercentSampleParams() {
  return {/*rate*/ 0.1,
          /*num_elements*/ 20,
          /*output_dtypes*/ {DT_INT64},
          /*output_shapes*/ {PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

SamplingDatasetParams ZeroPercentSampleParams() {
  return {/*rate*/ 0.0,
          /*num_elements*/ 20,
          /*output_dtypes*/ {DT_INT64},
          /*output_shapes*/ {PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

std::vector<GetNextTestCase<SamplingDatasetParams>> GetNextTestCases() {
  return {
      // Test case 1: 100% sample should return all inputs
      {/*dataset_params=*/OneHundredPercentSampleParams(),
       /*expected_outputs=*/CreateTensors<int64>(TensorShape({}),
                                                 {{0}, {1}, {2}})},

      // Test case 2: 10% sample should return about 10% of inputs, and the
      // specific inputs returned shouldn't change across build environments.
      {/*dataset_params=*/TenPercentSampleParams(),
       /*expected_outputs=*/CreateTensors<int64>(TensorShape({}),
                                                 {{9}, {11}, {19}})},

      // Test case 3: 0% sample should return nothing and should not crash.
      {/*dataset_params=*/ZeroPercentSampleParams(), /*expected_outputs=*/{}}};
}

ITERATOR_GET_NEXT_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                         GetNextTestCases());

std::vector<DatasetNodeNameTestCase<SamplingDatasetParams>>
DatasetNodeNameTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_node_name=*/kNodeName}};
}

DATASET_NODE_NAME_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                         DatasetNodeNameTestCases());

std::vector<DatasetTypeStringTestCase<SamplingDatasetParams>>
DatasetTypeStringTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_dataset_type_string=*/name_utils::OpName(
               SamplingDatasetOp::kDatasetType)}};
}

DATASET_TYPE_STRING_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                           DatasetTypeStringTestCases());

std::vector<DatasetOutputDtypesTestCase<SamplingDatasetParams>>
DatasetOutputDtypesTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_output_dtypes=*/{DT_INT64}}};
}

DATASET_OUTPUT_DTYPES_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                             DatasetOutputDtypesTestCases());

std::vector<DatasetOutputShapesTestCase<SamplingDatasetParams>>
DatasetOutputShapesTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_output_shapes=*/{PartialTensorShape({})}}};
}

DATASET_OUTPUT_SHAPES_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                             DatasetOutputShapesTestCases());

std::vector<CardinalityTestCase<SamplingDatasetParams>> CardinalityTestCases() {
  return {{/*dataset_params=*/OneHundredPercentSampleParams(),
           /*expected_cardinality=*/kUnknownCardinality},
          {/*dataset_params=*/TenPercentSampleParams(),
           /*expected,cardinality=*/kUnknownCardinality},
          {/*dataset_params=*/ZeroPercentSampleParams(),
           /*expected_cardinality=*/kUnknownCardinality}};
}

DATASET_CARDINALITY_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                           CardinalityTestCases());

std::vector<IteratorOutputDtypesTestCase<SamplingDatasetParams>>
IteratorOutputDtypesTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_output_dtypes=*/{DT_INT64}}};
}

ITERATOR_OUTPUT_DTYPES_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                              IteratorOutputDtypesTestCases());

std::vector<IteratorOutputShapesTestCase<SamplingDatasetParams>>
IteratorOutputShapesTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_output_shapes=*/{PartialTensorShape({})}}};
}

ITERATOR_OUTPUT_SHAPES_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                              IteratorOutputShapesTestCases());

std::vector<IteratorPrefixTestCase<SamplingDatasetParams>>
IteratorOutputPrefixTestCases() {
  return {{/*dataset_params=*/TenPercentSampleParams(),
           /*expected_iterator_prefix=*/name_utils::IteratorPrefix(
               SamplingDatasetOp::kDatasetType, kIteratorPrefix)}};
}

ITERATOR_PREFIX_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                       IteratorOutputPrefixTestCases());

std::vector<IteratorSaveAndRestoreTestCase<SamplingDatasetParams>>
IteratorSaveAndRestoreTestCases() {
  return {{/*dataset_params=*/OneHundredPercentSampleParams(),
           /*breakpoints=*/{0, 2, 5},
           /*expected_outputs=*/
           CreateTensors<int64>(TensorShape({}), {{0}, {1}, {2}})},
          {/*dataset_params=*/TenPercentSampleParams(),
           /*breakpoints=*/{0, 2, 5},
           /*expected_outputs=*/
           CreateTensors<int64>(TensorShape({}), {{9}, {11}, {19}})},
          {/*dataset_params=*/ZeroPercentSampleParams(),
           /*breakpoints=*/{0, 2, 5},
           /*expected_outputs=*/{}}};
}

ITERATOR_SAVE_AND_RESTORE_TEST_P(SamplingDatasetOpTest, SamplingDatasetParams,
                                 IteratorSaveAndRestoreTestCases());

}  // namespace
}  // namespace experimental
}  // namespace data
}  // namespace tensorflow
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// nonrecourse_loan.cpp
// --------------------
//
// Author: Parsiad Azimzadeh, Peter Forsyth
////////////////////////////////////////////////////////////////////////////////

#include <QuantPDE/Core>
#include <QuantPDE/Modules/Lambdas>
#include <QuantPDE/Modules/Operators>

using namespace QuantPDE;
using namespace QuantPDE::Modules;

////////////////////////////////////////////////////////////////////////////////

#include <algorithm> // max, min
#include <iomanip>   // setw
#include <iostream>  // cout, cerr
#include <cmath>     // exp

using namespace std;

////////////////////////////////////////////////////////////////////////////////
// Default constants
////////////////////////////////////////////////////////////////////////////////

Real beta_lo         = 0.8;   // Low trigger
Real beta_hi         = 0.9;   // High trigger

Real S_0             = 125.;  // Initial stock value
Real L_0             = 100.;  // Initial loan value
Real L_hat           = 100.;  // Representative value

Real r               = 0.04;  // Interest rate
Real s_0             = 0.02;  // Spread
Real sigma           = 0.2;   // Volatility

Real lambda          = 0.1;  // Jump arrival rate
Real mu_xi           = -.8;   // Mean jump amplitude
Real sigma_xi        = .42;   // Jump amplitude standard deviation

Real T               = 1.;    // Expiry

int borrowerEvents   = -1;    // Borrower events (-1 for all times)
int bankEvents       = 4;     // Bank events (-1 for all times)
int interestPayments = 4;     // Interest payments (once a quarter)

int N                = 12;    // Initial number of steps
int maxRefinement    = 5;     // Maximum number of times to refine

////////////////////////////////////////////////////////////////////////////////

/**
 * Controls the output of the program.
 */
enum class ProgramOperation {
	PLOT_DATA, /**< outputs plotting data */
	PLOT_DATA_VS_SPREAD, /**< outputs plotting data with spread as x-axis */
	FAIR_SPREAD, /**< computes the fair spread */
	FIXED_SPREAD /**< convergence test for a fixed spread */
};
ProgramOperation op = ProgramOperation::PLOT_DATA_VS_SPREAD;

////////////////////////////////////////////////////////////////////////////////

std::vector<Real> interestPaymentDates; // Sorted (ascending) vector of interest
                                        // payment dates; initialized in main()

/**
 * Payoff from the bank's perspective for representative value of L.
 * @param S The stock value at the expiry.
 * @return The payoff min(S, L_hat).
 */
Real payoff(Real S) { return min(S, L_hat); }

/**
 * Accrued interest at a particular time between coupon dates.
 * @param t The particular time.
 * @return e^((r+s)(t-t_p)) where t_p is the previous coupon date.
 */
Real accruedInterest(Real s, Real t) {
	// Binary search for interest payment date
	int lo = 0;
	int hi = interestPaymentDates.size() - 1;

	if(t > interestPaymentDates[hi]) {
		lo = hi;
	} else {
		while(lo < hi - 1) {
			int mid = (lo + hi) / 2;
			if(t <= interestPaymentDates[mid]) {
				hi = mid;
			} else {
				lo = mid;
			}
		}
	}

	// Previous interest payment time
	const Real t_previous = interestPaymentDates[lo];

	const Real A_t = exp( (r + s) * (t - t_previous) );
	return A_t;
}

////////////////////////////////////////////////////////////////////////////////

/**
 * Solve the nonrecourse stock loan problem with fixed spread.
 * @param s A fixed value of the spread.
 * @return The solution U(S, L) as a lambda function that can be queried at any
 *         point.
 */
Function2 solve(RectilinearGrid1 &grid, Real s);

/**
 * Main code.
 */
int main(int argc, char **argv) {
	// TODO: Initial grid should have node at S_0 and L_hat

	// Initial grid
	RectilinearGrid1 initialGrid(
		(S_0 / 100.) * Axis {
			0., 10., 20., 30., 40., 50., 60., 70.,
			75., 80.,
			84., 88., 92.,
			94., 96., 98., 100., 102., 104., 106., 108., 110.,
			114., 118.,
			123.,
			130., 140., 150.,
			175.,
			225.,
			300.,
			750.,
			2000.,
			10000.
		}
	);

	// Populate vector of interest payment dates
	{
		interestPaymentDates.reserve(interestPayments);
		const Real dt = T / interestPayments;

		interestPaymentDates.reserve(interestPayments);
		for(int i = 0; i <= interestPayments; ++i) {
			interestPaymentDates.push_back(dt * i);
		}
	} // 2015-02-28: checked

	cout.precision(12); // Precision
	constexpr int td = 20; // Spacing used to print

	if(op == ProgramOperation::PLOT_DATA) {

		// Double the number of timesteps as many times as necessary
		for(int i = 0; i < maxRefinement; ++i) { N *= 2; }

		// Refine grid ref times
		auto grid = initialGrid.refined( maxRefinement );

		// Fixed spread computation
		auto U = solve(grid, s_0);

		// Print grid
		RectilinearGrid2 printGrid(
			grid[0], // Axis from computational grid
			grid[0]
		);

		// Print U at all grid nodes
		cout << accessor(printGrid, U);

	} else if(op == ProgramOperation::PLOT_DATA_VS_SPREAD) {

		// Double the number of timesteps as many times as necessary
		for(int i = 0; i < maxRefinement; ++i) { N *= 2; }

		// Refine grid ref times
		auto grid = initialGrid.refined( maxRefinement );

		// TODO: Allow user to choose coarseness and bounds
		RectilinearGrid1 spreads( Axis::uniform(0, 2*r, 10) );

		// U as a function of the spread
		auto U_spread = [&] (Real spread) {
			auto U = solve(grid, spread);
			return U(S_0, L_0);
		};

		// Print U_spread for all spreads on the grid
		cout << accessor(spreads, U_spread);

	} else if(op == ProgramOperation::FAIR_SPREAD) {

		// TODO
		throw 1;

	} else if(op == ProgramOperation::FIXED_SPREAD) {

		// Print headers
		cout
			<< setw(td) << "Nodes"           << "\t"
			<< setw(td) << "Time Steps"      << "\t"
			<< setw(td) << "Value"           << "\t"
			<< setw(td) << "Change"          << "\t"
			<< setw(td) << "Ratio"
			<< endl
		;

		Real value, previousValue = nan(""), previousChange = nan("");
		for(int ref = 0; ref <= maxRefinement; ++ref, N *= 2) {
			// Refine grid ref times
			auto grid = initialGrid.refined( ref );

			// Solve U(S)
			auto U = solve(grid, s_0);

			// Query U at the point (S_0, L_0)
			value = U(S_0, L_0);

			////////////////////////////////////////////////////////
			// Print table rows
			////////////////////////////////////////////////////////

			Real
				change = value - previousValue,
				ratio = previousChange / change
			;

			cout
				<< setw(td) << grid.size() << "\t"
				<< setw(td) << N           << "\t"
				<< setw(td) << value       << "\t"
				<< setw(td) << change      << "\t"
				<< setw(td) << ratio       << "\t"
				<< endl;

			previousChange = change;
			previousValue = value;
		}

	}

	return 0;
}

////////////////////////////////////////////////////////////////////////////////

Function2 solve(RectilinearGrid1 &grid, Real s) {
	// Constant step-size
	ReverseConstantStepper stepper(
		0.,   // Initial time
		T,    // Expiry time
		T / N // Timestep size
	);

	////////////////////////////////////////////////////////////////////////

	// Order of events (forward in time)
	// 1. Borrower: walk-away or repay
	// 2. Bank: top-up or liquidate
	// 3. Interest payment

	// Apply events at all times
	if(borrowerEvents < 0) { borrowerEvents = N; }
	if(bankEvents     < 0) { bankEvents     = N; }

	////////////////////////////////////////////////////////////////////////

	{ // <BorrowerEvent>

	// Time between borrower events
	const Real dt = T / borrowerEvents;

	for(int i = 0; i < borrowerEvents; ++i) {
		const Real t_i = dt * i;

		// Accrued interest
		const Real A = accruedInterest(s, t_i);

		stepper.add(
			t_i,
			[=] (const Interpolant1 &U, Real S) {
				return min( U(S), min(L_hat * A, S) );
			},
			grid
		);
	}

	} // </BorrowerEvent>
	// 2015-03-04: checked; respects monotonicity

	////////////////////////////////////////////////////////////////////////

	{ // <BankEvent>

	// Time between bank events
	const Real dt = T / bankEvents;

	for(int i = 0; i < bankEvents; ++i) {
		const Real t_i = dt * i;

		// Accrued interest
		const Real A = accruedInterest(s, t_i);

		stepper.add(
			t_i,
			[=] (const Interpolant1 &U, Real S) {
				// Continuation value
				Real best = U(S);

				// Value-to-loan ratio
				const Real R = L_hat / S;

				// R is above high trigger
				if(R > beta_hi) {

					// Option to liquidate
					const Real tmp = min(L_hat * A, S);
					if(tmp > best) {
						best = tmp;
					}

				// R is between low and high triggers
				} else if(R >= beta_lo) {
					const Real R_0 = L_0 / S_0;

					{ // Top-up with shares
						const Real tmp = U(L_hat / R_0);
						if(tmp > best) {
							best = tmp;
						}
					}

					// Top-up with cash
					const Real tmp = S * R_0 / L_hat
							* U(L_hat / R_0)
							+ (L_hat - S * R_0) * A;
					;
					if(tmp > best) {
						best = tmp;
					}
				}

				return best;
			},
			grid
		);
	}

	} // </BankEvent>

	////////////////////////////////////////////////////////////////////////

	{ // <InterestPayment>

	// Add interest payment events (skip initial time)
	for(
		auto it = interestPaymentDates.begin() + 1;
		it != interestPaymentDates.end();
		++it
	) {
		// Time at which interest payment takes place
		const Real t_i = *it;

		// Accrued interest
		const Real A = accruedInterest(s, t_i);

		stepper.add(
			t_i,
			[=] (const Interpolant1 &U, Real S) {
				return U(S) + L_hat * (A - 1.);
			},
			grid
		);
	}

	} // </InterestPayment>
	// 2015-03-04: checked; respects monotonicity; if spread is zero and
	//             events are off, then U(S_0) -> L_0 as S_0 -> infinity
	//             (i.e. the bank just gets the loan + interest back)

	// TODO: Dividends

	////////////////////////////////////////////////////////////////////////

	// Jump-diffusion operator
	BlackScholesJumpDiffusion1 bs(
		grid,

		r,      // Interest
		sigma,  // Volatility
		0.,     // Continuous dividend rate

		lambda, // Mean arrival time
		lognormal(mu_xi, sigma_xi) // Log-normal probability density
	);
	bs.setIteration(stepper);

	// No jump-diffusion test
	//BlackScholes1 bs(grid, r, sigma, 0.);

	// Discretization method
	typedef ReverseBDFTwo1 Discretization;
	Discretization discretization(grid, bs);
	discretization.setIteration(stepper);

	// Linear system solver
	BiCGSTABSolver solver;
	auto U = stepper.solve(
		grid,           // Domain
		payoff,         // Initial condition
		discretization, // Root of linear system tree
		solver          // Linear system solver
	);

	////////////////////////////////////////////////////////////////////////

	// Similarity reduction
	return [=] (Real S, Real L) {
		if(L <= 0.) { return 0.; }
		const Real alpha = L_hat / L;
		const Real value = U(alpha * S) / alpha;
		return value;
	};
	// 2015-02-28: checked; without events, exp(-r * T) * L_0 - value is the
	//                      price (at t=0) of a put with strike L_0
}
<commit_msg>Changed plotting function in stock loan code.<commit_after>////////////////////////////////////////////////////////////////////////////////
// nonrecourse_loan.cpp
// --------------------
//
// Author: Parsiad Azimzadeh, Peter Forsyth
////////////////////////////////////////////////////////////////////////////////

#include <QuantPDE/Core>
#include <QuantPDE/Modules/Lambdas>
#include <QuantPDE/Modules/Operators>

using namespace QuantPDE;
using namespace QuantPDE::Modules;

////////////////////////////////////////////////////////////////////////////////

#include <algorithm> // max, min
#include <iomanip>   // setw
#include <iostream>  // cout, cerr
#include <cmath>     // exp

using namespace std;

////////////////////////////////////////////////////////////////////////////////
// Default constants
////////////////////////////////////////////////////////////////////////////////

Real beta_lo         = 0.8;   // Low trigger
Real beta_hi         = 0.9;   // High trigger

Real S_0             = 125.;  // Initial stock value
Real L_0             = 100.;  // Initial loan value
Real L_hat           = 100.;  // Representative value

Real r               = 0.04;  // Interest rate
Real s_0             = 0.0;   // Spread
Real sigma           = 0.2;   // Volatility

Real lambda          = 0.1;  // Jump arrival rate
Real mu_xi           = -.8;   // Mean jump amplitude
Real sigma_xi        = .42;   // Jump amplitude standard deviation

Real T               = 1.;    // Expiry

int borrowerEvents   = -1;    // Borrower events (-1 for all times)
int bankEvents       = -1;    // Bank events (-1 for all times)
int interestPayments = 4;     // Interest payments (once a quarter)

int N                = 12;    // Initial number of steps
int maxRefinement    = 5;     // Maximum number of times to refine

////////////////////////////////////////////////////////////////////////////////

/**
 * Controls the output of the program.
 */
enum class ProgramOperation {
	PLOT_DATA, /**< outputs plotting data */
	PLOT_DATA_VS_SPREAD, /**< outputs plotting data with spread as x-axis */
	FAIR_SPREAD, /**< computes the fair spread */
	FIXED_SPREAD /**< convergence test for a fixed spread */
};
ProgramOperation op = ProgramOperation::PLOT_DATA_VS_SPREAD;

////////////////////////////////////////////////////////////////////////////////

std::vector<Real> interestPaymentDates; // Sorted (ascending) vector of interest
                                        // payment dates; initialized in main()

/**
 * Payoff from the bank's perspective for representative value of L.
 * @param S The stock value at the expiry.
 * @return The payoff min(S, L_hat).
 */
Real payoff(Real S) { return min(S, L_hat); }

/**
 * Accrued interest at a particular time between coupon dates.
 * @param t The particular time.
 * @return e^((r+s)(t-t_p)) where t_p is the previous coupon date.
 */
Real accruedInterest(Real s, Real t) {
	// Binary search for interest payment date
	int lo = 0;
	int hi = interestPaymentDates.size() - 1;

	if(t > interestPaymentDates[hi]) {
		lo = hi;
	} else {
		while(lo < hi - 1) {
			int mid = (lo + hi) / 2;
			if(t <= interestPaymentDates[mid]) {
				hi = mid;
			} else {
				lo = mid;
			}
		}
	}

	// Previous interest payment time
	const Real t_previous = interestPaymentDates[lo];

	const Real A_t = exp( (r + s) * (t - t_previous) );
	return A_t;
}

////////////////////////////////////////////////////////////////////////////////

/**
 * Solve the nonrecourse stock loan problem with fixed spread.
 * @param s A fixed value of the spread.
 * @return The solution U(S, L) as a lambda function that can be queried at any
 *         point.
 */
Function2 solve(RectilinearGrid1 &grid, Real s);

/**
 * Main code.
 */
int main(int argc, char **argv) {
	// TODO: Initial grid should have node at S_0 and L_hat

	// Initial grid
	RectilinearGrid1 initialGrid(
		(S_0 / 100.) * Axis {
			0., 10., 20., 30., 40., 50., 60., 70.,
			75., 80.,
			84., 88., 92.,
			94., 96., 98., 100., 102., 104., 106., 108., 110.,
			114., 118.,
			123.,
			130., 140., 150.,
			175.,
			225.,
			300.,
			750.,
			2000.,
			10000.
		}
	);

	// Populate vector of interest payment dates
	{
		interestPaymentDates.reserve(interestPayments);
		const Real dt = T / interestPayments;

		interestPaymentDates.reserve(interestPayments);
		for(int i = 0; i <= interestPayments; ++i) {
			interestPaymentDates.push_back(dt * i);
		}
	} // 2015-02-28: checked

	cout.precision(12); // Precision
	constexpr int td = 20; // Spacing used to print

	if(op == ProgramOperation::PLOT_DATA) {

		// Double the number of timesteps as many times as necessary
		for(int i = 0; i < maxRefinement; ++i) { N *= 2; }

		// Refine grid ref times
		auto grid = initialGrid.refined( maxRefinement );

		// Fixed spread computation
		auto U = solve(grid, s_0);

		// Print U(S, L_0) (fixed L_0) at all grid nodes
		cout << accessor( grid, [&] (Real S) { return U(S, L_0); } );

	} else if(op == ProgramOperation::PLOT_DATA_VS_SPREAD) {

		// Double the number of timesteps as many times as necessary
		for(int i = 0; i < maxRefinement; ++i) { N *= 2; }

		// Refine grid ref times
		auto grid = initialGrid.refined( maxRefinement );

		// TODO: Allow user to choose coarseness and bounds
		RectilinearGrid1 spreads( Axis::uniform(0, 2*r, N) );

		// U as a function of the spread
		auto U_spread = [&] (Real spread) {
			auto U = solve(grid, spread);
			return U(S_0, L_0);
		};

		// Print U_spread for all spreads on the grid
		cout << accessor(spreads, U_spread);

	} else if(op == ProgramOperation::FAIR_SPREAD) {

		// TODO
		throw 1;

	} else if(op == ProgramOperation::FIXED_SPREAD) {

		// Print headers
		cout
			<< setw(td) << "Nodes"           << "\t"
			<< setw(td) << "Time Steps"      << "\t"
			<< setw(td) << "Value"           << "\t"
			<< setw(td) << "Change"          << "\t"
			<< setw(td) << "Ratio"
			<< endl
		;

		Real value, previousValue = nan(""), previousChange = nan("");
		for(int ref = 0; ref <= maxRefinement; ++ref, N *= 2) {
			// Refine grid ref times
			auto grid = initialGrid.refined( ref );

			// Solve U(S)
			auto U = solve(grid, s_0);

			// Query U at the point (S_0, L_0)
			value = U(S_0, L_0);

			////////////////////////////////////////////////////////
			// Print table rows
			////////////////////////////////////////////////////////

			Real
				change = value - previousValue,
				ratio = previousChange / change
			;

			cout
				<< setw(td) << grid.size() << "\t"
				<< setw(td) << N           << "\t"
				<< setw(td) << value       << "\t"
				<< setw(td) << change      << "\t"
				<< setw(td) << ratio       << "\t"
				<< endl;

			previousChange = change;
			previousValue = value;
		}

	}

	return 0;
}

////////////////////////////////////////////////////////////////////////////////

Function2 solve(RectilinearGrid1 &grid, Real s) {
	// Constant step-size
	ReverseConstantStepper stepper(
		0.,   // Initial time
		T,    // Expiry time
		T / N // Timestep size
	);

	////////////////////////////////////////////////////////////////////////

	// Order of events (forward in time)
	// 1. Borrower: walk-away or repay
	// 2. Bank: top-up or liquidate
	// 3. Interest payment

	// Apply events at all times
	if(borrowerEvents < 0) { borrowerEvents = N; }
	if(bankEvents     < 0) { bankEvents     = N; }

	////////////////////////////////////////////////////////////////////////

	{ // <BorrowerEvent>

	// Time between borrower events
	const Real dt = T / borrowerEvents;

	for(int i = 0; i < borrowerEvents; ++i) {
		const Real t_i = dt * i;

		// Accrued interest
		const Real A = accruedInterest(s, t_i);

		stepper.add(
			t_i,
			[=] (const Interpolant1 &U, Real S) {
				return min( U(S), min(L_hat * A, S) );
			},
			grid
		);
	}

	} // </BorrowerEvent>
	// 2015-03-04: checked; respects monotonicity

	////////////////////////////////////////////////////////////////////////

	{ // <BankEvent>

	// Time between bank events
	const Real dt = T / bankEvents;

	for(int i = 0; i < bankEvents; ++i) {
		const Real t_i = dt * i;

		// Accrued interest
		const Real A = accruedInterest(s, t_i);

		stepper.add(
			t_i,
			[=] (const Interpolant1 &U, Real S) {
				// Continuation value
				Real best = U(S);

				// Value-to-loan ratio
				const Real R = L_hat / S;

				// R is above high trigger
				if(R > beta_hi) {

					// Option to liquidate
					const Real tmp = min(L_hat * A, S);
					if(tmp > best) {
						best = tmp;
					}

				// R is between low and high triggers
				} else if(R >= beta_lo) {
					const Real R_0 = L_0 / S_0;

					{ // Top-up with shares
						const Real tmp = U(L_hat / R_0);
						if(tmp > best) {
							best = tmp;
						}
					}

					// Top-up with cash
					const Real tmp = S * R_0 / L_hat
							* U(L_hat / R_0)
							+ (L_hat - S * R_0) * A;
					;
					if(tmp > best) {
						best = tmp;
					}
				}

				return best;
			},
			grid
		);
	}

	} // </BankEvent>

	////////////////////////////////////////////////////////////////////////

	{ // <InterestPayment>

	// Add interest payment events (skip initial time)
	for(
		auto it = interestPaymentDates.begin() + 1;
		it != interestPaymentDates.end();
		++it
	) {
		// Time at which interest payment takes place
		const Real t_i = *it;

		// Accrued interest
		const Real A = accruedInterest(s, t_i);

		stepper.add(
			t_i,
			[=] (const Interpolant1 &U, Real S) {
				return U(S) + L_hat * (A - 1.);
			},
			grid
		);
	}

	} // </InterestPayment>
	// 2015-03-04: checked; respects monotonicity; if spread is zero and
	//             events are off, then U(S_0) -> L_0 as S_0 -> infinity
	//             (i.e. the bank just gets the loan + interest back)

	// TODO: Dividends

	////////////////////////////////////////////////////////////////////////

	// Jump-diffusion operator
	BlackScholesJumpDiffusion1 bs(
		grid,

		r,      // Interest
		sigma,  // Volatility
		0.,     // Continuous dividend rate

		lambda, // Mean arrival time
		lognormal(mu_xi, sigma_xi) // Log-normal probability density
	);
	bs.setIteration(stepper);

	// No jump-diffusion test
	//BlackScholes1 bs(grid, r, sigma, 0.);

	// Discretization method
	typedef ReverseBDFTwo1 Discretization;
	Discretization discretization(grid, bs);
	discretization.setIteration(stepper);

	// Linear system solver
	BiCGSTABSolver solver;
	auto U = stepper.solve(
		grid,           // Domain
		payoff,         // Initial condition
		discretization, // Root of linear system tree
		solver          // Linear system solver
	);

	////////////////////////////////////////////////////////////////////////

	// Similarity reduction
	return [=] (Real S, Real L) {
		if(L <= 0.) { return 0.; }
		const Real alpha = L_hat / L;
		const Real value = U(alpha * S) / alpha;
		return value;
	};
	// 2015-02-28: checked; without events, exp(-r * T) * L_0 - value is the
	//                      price (at t=0) of a put with strike L_0
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sdrmediawindow.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 00:03:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_SDRMEDIAWIMNDOW_HXX

#include <avmedia/mediawindow.hxx>

namespace sdr { namespace contact {

// ------------------
// - SdrMediaWindow -
// ------------------

class ViewObjectContactOfSdrMediaObj;

class SdrMediaWindow : public ::avmedia::MediaWindow
{
public:

                            SdrMediaWindow( Window* pParent, ViewObjectContactOfSdrMediaObj& rViewObjContact );
                            ~SdrMediaWindow();

        virtual void        MouseMove( const MouseEvent& rMEvt );
        virtual void        MouseButtonDown( const MouseEvent& rMEvt );
        virtual void        MouseButtonUp( const MouseEvent& rMEvt );

        virtual void        KeyInput( const KeyEvent& rKEvt );
        virtual void        KeyUp( const KeyEvent& rKEvt );

        virtual void        Command( const CommandEvent& rCEvt );

        virtual sal_Int8    AcceptDrop( const AcceptDropEvent& rEvt );
        virtual sal_Int8    ExecuteDrop( const ExecuteDropEvent& rEvt );

        virtual void        StartDrag( sal_Int8 nAction, const Point& rPosPixel );

private:

    ViewObjectContactOfSdrMediaObj& mrViewObjectContactOfSdrMediaObj;
};

} }

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.3.1254); FILE MERGED 2008/03/31 14:23:10 rt 1.3.1254.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sdrmediawindow.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SDR_CONTACT_SDRMEDIAWIMNDOW_HXX

#include <avmedia/mediawindow.hxx>

namespace sdr { namespace contact {

// ------------------
// - SdrMediaWindow -
// ------------------

class ViewObjectContactOfSdrMediaObj;

class SdrMediaWindow : public ::avmedia::MediaWindow
{
public:

                            SdrMediaWindow( Window* pParent, ViewObjectContactOfSdrMediaObj& rViewObjContact );
                            ~SdrMediaWindow();

        virtual void        MouseMove( const MouseEvent& rMEvt );
        virtual void        MouseButtonDown( const MouseEvent& rMEvt );
        virtual void        MouseButtonUp( const MouseEvent& rMEvt );

        virtual void        KeyInput( const KeyEvent& rKEvt );
        virtual void        KeyUp( const KeyEvent& rKEvt );

        virtual void        Command( const CommandEvent& rCEvt );

        virtual sal_Int8    AcceptDrop( const AcceptDropEvent& rEvt );
        virtual sal_Int8    ExecuteDrop( const ExecuteDropEvent& rEvt );

        virtual void        StartDrag( sal_Int8 nAction, const Point& rPosPixel );

private:

    ViewObjectContactOfSdrMediaObj& mrViewObjectContactOfSdrMediaObj;
};

} }

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SwNodeNum.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: obo $ $Date: 2007-07-18 14:27:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include <svx/svxenum.hxx>
#include <SwNodeNum.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <stdio.h>

SwNodeNum::SwNodeNum()
    : SwNumberTreeNode(), mpTxtNode(NULL), mpNumRule(NULL), mnStart(1),
      mbRestart(false)
{
}

SwNodeNum::SwNodeNum(const SwNodeNum & rNodeNum)
    : SwNumberTreeNode(rNodeNum), mpTxtNode(NULL),
      mpNumRule(NULL), mnStart(rNodeNum.mnStart),
      mbRestart(rNodeNum.mbRestart)
{
}

SwNodeNum::~SwNodeNum()
{
}

void SwNodeNum::SetTxtNode(SwTxtNode * pTxtNode)
{
    mpTxtNode = pTxtNode;
}

SwTxtNode * SwNodeNum::GetTxtNode() const
{
    return mpTxtNode;
}

void SwNodeNum::SetNumRule(SwNumRule * pRule)
{
    mpNumRule = pRule;
}

SwNumRule * SwNodeNum::GetNumRule() const
{
    return mpNumRule;
}

SwPosition SwNodeNum::GetPosition() const
{
    return SwPosition(*mpTxtNode);
}

SwNumberTreeNode * SwNodeNum::Create() const
{
    SwNodeNum * pResult = new SwNodeNum();

    pResult->SetNumRule(mpNumRule);

    return pResult;
}

SwNumberTreeNode * SwNodeNum::Copy() const
{
    return new SwNodeNum(*this);
}

void SwNodeNum::RemoveChild(SwNumberTreeNode * _pChild)
{
    // --> OD 2006-04-21 #i64311#
    // remove child before resetting numbering rule of child.
    SwNumberTreeNode::RemoveChild(_pChild);

    SwNodeNum * pChild = static_cast<SwNodeNum*>(_pChild);
    pChild->SetNumRule(NULL);
    // <--

}

bool SwNodeNum::IsNotifiable() const
{
    bool aResult = true;

    if (mpTxtNode)
        aResult = mpTxtNode->IsNotifiable();

    return aResult;
}

bool SwNodeNum::IsNotificationEnabled() const
{
    bool aResult = true;

    if (mpTxtNode)
        aResult = mpTxtNode->IsNotificationEnabled();

    return aResult;
}

bool SwNodeNum::IsContinuous() const
{
    bool aResult = false;

    // --> OD 2006-04-21 #i64311#
    if ( mpNumRule )
    {
        aResult = mpNumRule->IsContinusNum();
    }
    else if ( mpParent )
    {
        aResult = mpParent->IsContinuous();
    }
    else
    {
        ASSERT( false, "<SwNodeNum::IsContinuous()> - OD debug" );
    }
    // <--

    return aResult;
}

bool SwNodeNum::IsCounted() const
{
    bool aResult = false;

    if (mpTxtNode)
    {
        // --> OD 2006-01-25 #i59559#
        // <SwTxtNode::IsCounted()> determines, if a text node is counted for numbering
//        const SwNumFmt * pNumFmt = GetNumFmt();
//        if (pNumFmt)
//        {
//            sal_Int16 nType = pNumFmt->GetNumberingType();
//            if ( nType != SVX_NUM_NUMBER_NONE)
//                aResult = mpTxtNode->IsCounted();
//        }
        aResult = mpTxtNode->IsCounted();
        // <--
    }
    else
        aResult = SwNumberTreeNode::IsCounted();

    return aResult;
}

// --> OD 2006-04-26 #i64010#
bool SwNodeNum::HasCountedChildren() const
{
    bool bResult = false;

    tSwNumberTreeChildren::iterator aIt;

    for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
    {
        SwNodeNum* pChild( dynamic_cast<SwNodeNum*>(*aIt) );
        ASSERT( pChild,
                "<SwNodeNum::HasCountedChildren()> - unexcepted type of child -> please inform OD" );
        if ( pChild &&
             ( pChild->IsCountedForNumbering() ||
               pChild->HasCountedChildren() ) )
        {
            bResult = true;

            break;
        }
    }

    return bResult;
}
// <--
// --> OD 2006-04-26 #i64010#
bool SwNodeNum::IsCountedForNumbering() const
{
    return IsCounted() &&
           ( IsPhantom() ||                 // phantoms
             !GetTxtNode() ||               // root node
             GetTxtNode()->HasNumber() ||   // text node
             GetTxtNode()->HasBullet() );   // text node
}
// <--

void SwNodeNum::NotifyNode()
{
    ValidateMe();

    if (mpTxtNode)
    {
        mpTxtNode->NumRuleChgd();
    }
}

bool SwNodeNum::LessThan(const SwNumberTreeNode & rNode) const
{
    bool bResult = false;
    const SwNodeNum & rTmpNode = static_cast<const SwNodeNum &>(rNode);

    if (mpTxtNode == NULL && rTmpNode.mpTxtNode != NULL)
        bResult = true;
    else if (mpTxtNode != NULL && rTmpNode.mpTxtNode != NULL)
    {
        SwPosition aMyPos(*mpTxtNode);
        SwPosition aHisPos(*rTmpNode.mpTxtNode);

        bResult = (aMyPos < aHisPos) ? true : false;
    }

    return bResult;
}

void SwNodeNum::SetRestart(bool bRestart)
{
    // --> OD 2005-10-19 #126009#
    // - improvement: invalidation only, if <IsRestart()> state changes.
    const bool bInvalidate( mbRestart != bRestart );
    // <--
    mbRestart = bRestart;

    // --> OD 2005-10-19 #126009#
    if ( bInvalidate )
    {
        InvalidateMe();
        NotifyInvalidSiblings();
    }
    // <--
}

bool SwNodeNum::IsRestart() const
{
    return mbRestart;
}

void SwNodeNum::SetStart(SwNumberTreeNode::tSwNumTreeNumber nStart)
{
    // --> OD 2005-10-19 #126009#
    // - improvement: invalidation only, if <IsRestart()> state changes.
    const bool bInvalidate( mnStart != nStart );
    // <--
    mnStart = nStart;

    // --> OD 2005-10-19 #126009#
    if ( bInvalidate )
    {
        InvalidateMe();
        NotifyInvalidSiblings();
    }
}

bool SwNodeNum::IsCountPhantoms() const
{
    bool bResult = true;

    // --> OD 2006-04-21 #i64311#
    // phantoms aren't counted in consecutive numbering rules
    if ( mpNumRule )
        bResult = !mpNumRule->IsContinusNum() &&
                  mpNumRule->IsCountPhantoms();
    else
    {
        ASSERT( false,
                "<SwNodeNum::IsCountPhantoms(): missing numbering rule - please inform OD" );
    }
    // <--

    return bResult;
}

SwNumberTreeNode::tSwNumTreeNumber SwNodeNum::GetStart() const
{
    tSwNumTreeNumber aResult = 1;

    // --> OD 2005-11-16 #i57919# - consider that start value <USHRT_MAX>
    // indicates, that the numbering is restarted at this node with the
    // start value, which is set at the corresponding numbering level.
    if ( IsRestart() && mnStart != USHRT_MAX )
    // <--
    {
        aResult = mnStart;
    }
    else
    {
        SwNumRule * pRule = GetNumRule();

        if (pRule)
        {
            // --> OD 2006-04-24 #i64311#
            // consider root number tree node
            // --> OD 2006-05-24 #i65705# - correct fix for i64311
            int nLevel = GetParent() ? GetLevel() : 0;
            // <--

            if (nLevel >= 0 && nLevel < MAXLEVEL)
            {
                const SwNumFmt * pFmt = pRule->GetNumFmt(nLevel);

                if (pFmt)
                    aResult = pFmt->GetStart();
            }
        }
    }

    return aResult;
}

String SwNodeNum::ToString() const
{
    String aResult("[ ", RTL_TEXTENCODING_ASCII_US);

    if (GetTxtNode())
    {
        char aBuffer[256];

        sprintf(aBuffer, "%p ", GetTxtNode());

        aResult += String(aBuffer, RTL_TEXTENCODING_ASCII_US);
        aResult += String::CreateFromInt32(GetPosition().nNode.GetIndex());
    }
    else
        aResult += String("*", RTL_TEXTENCODING_ASCII_US);

    aResult += String(" ", RTL_TEXTENCODING_ASCII_US);

    unsigned int nLvl = GetLevel();
    aResult += String::CreateFromInt32(nLvl);

    aResult += String(": ", RTL_TEXTENCODING_ASCII_US);

    tNumberVector aNumVector;

    _GetNumberVector(aNumVector, false);

    for (unsigned int n = 0; n < aNumVector.size(); n++)
    {
        if (n > 0)
            aResult += String(", ", RTL_TEXTENCODING_ASCII_US);

        aResult += String::CreateFromInt32(aNumVector[n]);
    }

    if (IsCounted())
//        aResult += String(" counted", RTL_TEXTENCODING_ASCII_US);
        aResult += String(" C", RTL_TEXTENCODING_ASCII_US);

    if (IsRestart())
    {
//        aResult += String(" restart(", RTL_TEXTENCODING_ASCII_US);
        aResult += String(" R(", RTL_TEXTENCODING_ASCII_US);
        aResult += String::CreateFromInt32(GetStart());
        aResult += String(")", RTL_TEXTENCODING_ASCII_US);
    }

    if (! IsValid())
//        aResult += String(" invalid", RTL_TEXTENCODING_ASCII_US);
        aResult += String(" I", RTL_TEXTENCODING_ASCII_US);

    aResult += String(" ]", RTL_TEXTENCODING_ASCII_US);

    return aResult;
}

void SwNodeNum::SetLevel(unsigned int nLevel)
{
    ASSERT(nLevel >= 0 && nLevel < MAXLEVEL, "illegal level");

    if (mpParent)
    {
        SwNumRule * pRule = GetNumRule();

        if (pRule != mpNumRule || nLevel != GetLevel())
        {
            RemoveMe();

            if (pRule)
                pRule->AddNumber(this, nLevel);
        }
    }
}

// --> OD 2006-03-07 #131436#
void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum& rNodeNum )
{
    SwNodeNum* pRootNode = rNodeNum.GetParent()
                           ? dynamic_cast<SwNodeNum*>(rNodeNum.GetRoot())
                           : &rNodeNum;
    if ( !pRootNode )
    {
        // no root node -> nothing do.
        return;
    }

    // unregister all number tree node entries, which correspond to a text node,
    // about the deletion of the number tree root node.
    _UnregisterMeAndChildrenDueToRootDelete( *pRootNode );
}

void SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete( SwNodeNum& rNodeNum )
{
    const bool bIsPhantom( rNodeNum.IsPhantom() );
    tSwNumberTreeChildren::size_type nAllowedChildCount( 0 );
    bool bDone( false );
    while ( !bDone &&
            rNodeNum.GetChildCount() > nAllowedChildCount )
    {
        SwNodeNum* pChildNode( dynamic_cast<SwNodeNum*>((*rNodeNum.mChildren.begin())) );
        if ( !pChildNode )
        {
            ASSERT( false,
                    "<SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" );
            ++nAllowedChildCount;
            continue;
        }

        // Unregistering the last child of a phantom will destroy the phantom.
        // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to
        // be suppressed.
        if ( bIsPhantom && rNodeNum.GetChildCount() == 1 )
        {
            bDone = true;
        }

        _UnregisterMeAndChildrenDueToRootDelete( *pChildNode );
    }

    if ( !bIsPhantom )
    {
        SwTxtNode* pTxtNode( rNodeNum.GetTxtNode() );
        if ( pTxtNode )
        {
            pTxtNode->UnregisterNumber();
        }
    }
}
// <--
<commit_msg>INTEGRATION: CWS swwarnings (1.9.130); FILE MERGED 2007/08/20 15:22:48 tl 1.9.130.4: RESYNC: (1.10-1.11); FILE MERGED 2007/05/29 11:07:49 os 1.9.130.3: RESYNC: (1.9-1.10); FILE MERGED 2007/04/03 12:59:18 tl 1.9.130.2: #i69287# warning-free code 2007/03/12 08:05:26 fme 1.9.130.1: #i69287# Warning free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SwNodeNum.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 08:18:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include <svx/svxenum.hxx>
#include <SwNodeNum.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <stdio.h>

SwNodeNum::SwNodeNum()
    : SwNumberTreeNode(), mpTxtNode(NULL), mpNumRule(NULL), mnStart(1),
      mbRestart(false)
{
}

SwNodeNum::SwNodeNum(const SwNodeNum & rNodeNum)
    : SwNumberTreeNode(rNodeNum), mpTxtNode(NULL),
      mpNumRule(NULL), mnStart(rNodeNum.mnStart),
      mbRestart(rNodeNum.mbRestart)
{
}

SwNodeNum::~SwNodeNum()
{
}

void SwNodeNum::SetTxtNode(SwTxtNode * pTxtNode)
{
    mpTxtNode = pTxtNode;
}

SwTxtNode * SwNodeNum::GetTxtNode() const
{
    return mpTxtNode;
}

void SwNodeNum::SetNumRule(SwNumRule * pRule)
{
    mpNumRule = pRule;
}

SwNumRule * SwNodeNum::GetNumRule() const
{
    return mpNumRule;
}

SwPosition SwNodeNum::GetPosition() const
{
    return SwPosition(*mpTxtNode);
}

SwNumberTreeNode * SwNodeNum::Create() const
{
    SwNodeNum * pResult = new SwNodeNum();

    pResult->SetNumRule(mpNumRule);

    return pResult;
}

SwNumberTreeNode * SwNodeNum::Copy() const
{
    return new SwNodeNum(*this);
}

void SwNodeNum::RemoveChild(SwNumberTreeNode * _pChild)
{
    // --> OD 2006-04-21 #i64311#
    // remove child before resetting numbering rule of child.
    SwNumberTreeNode::RemoveChild(_pChild);

    SwNodeNum * pChild = static_cast<SwNodeNum*>(_pChild);
    pChild->SetNumRule(NULL);
    // <--

}

bool SwNodeNum::IsNotifiable() const
{
    bool aResult = true;

    if (mpTxtNode)
        aResult = mpTxtNode->IsNotifiable();

    return aResult;
}

bool SwNodeNum::IsNotificationEnabled() const
{
    bool aResult = true;

    if (mpTxtNode)
        aResult = mpTxtNode->IsNotificationEnabled();

    return aResult;
}

bool SwNodeNum::IsContinuous() const
{
    bool aResult = false;

    // --> OD 2006-04-21 #i64311#
    if ( mpNumRule )
    {
        aResult = mpNumRule->IsContinusNum();
    }
    else if ( mpParent )
    {
        aResult = mpParent->IsContinuous();
    }
    else
    {
        ASSERT( false, "<SwNodeNum::IsContinuous()> - OD debug" );
    }
    // <--

    return aResult;
}

bool SwNodeNum::IsCounted() const
{
    bool aResult = false;

    if (mpTxtNode)
    {
        // --> OD 2006-01-25 #i59559#
        // <SwTxtNode::IsCounted()> determines, if a text node is counted for numbering
//        const SwNumFmt * pNumFmt = GetNumFmt();
//        if (pNumFmt)
//        {
//            sal_Int16 nType = pNumFmt->GetNumberingType();
//            if ( nType != SVX_NUM_NUMBER_NONE)
//                aResult = mpTxtNode->IsCounted();
//        }
        aResult = mpTxtNode->IsCounted();
        // <--
    }
    else
        aResult = SwNumberTreeNode::IsCounted();

    return aResult;
}

// --> OD 2006-04-26 #i64010#
bool SwNodeNum::HasCountedChildren() const
{
    bool bResult = false;

    tSwNumberTreeChildren::iterator aIt;

    for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++)
    {
        SwNodeNum* pChild( dynamic_cast<SwNodeNum*>(*aIt) );
        ASSERT( pChild,
                "<SwNodeNum::HasCountedChildren()> - unexcepted type of child -> please inform OD" );
        if ( pChild &&
             ( pChild->IsCountedForNumbering() ||
               pChild->HasCountedChildren() ) )
        {
            bResult = true;

            break;
        }
    }

    return bResult;
}
// <--
// --> OD 2006-04-26 #i64010#
bool SwNodeNum::IsCountedForNumbering() const
{
    return IsCounted() &&
           ( IsPhantom() ||                 // phantoms
             !GetTxtNode() ||               // root node
             GetTxtNode()->HasNumber() ||   // text node
             GetTxtNode()->HasBullet() );   // text node
}
// <--

void SwNodeNum::NotifyNode()
{
    ValidateMe();

    if (mpTxtNode)
    {
        mpTxtNode->NumRuleChgd();
    }
}

bool SwNodeNum::LessThan(const SwNumberTreeNode & rNode) const
{
    bool bResult = false;
    const SwNodeNum & rTmpNode = static_cast<const SwNodeNum &>(rNode);

    if (mpTxtNode == NULL && rTmpNode.mpTxtNode != NULL)
        bResult = true;
    else if (mpTxtNode != NULL && rTmpNode.mpTxtNode != NULL)
    {
        SwPosition aMyPos(*mpTxtNode);
        SwPosition aHisPos(*rTmpNode.mpTxtNode);

        bResult = (aMyPos < aHisPos) ? true : false;
    }

    return bResult;
}

void SwNodeNum::SetRestart(bool bRestart)
{
    // --> OD 2005-10-19 #126009#
    // - improvement: invalidation only, if <IsRestart()> state changes.
    const bool bInvalidate( mbRestart != bRestart );
    // <--
    mbRestart = bRestart;

    // --> OD 2005-10-19 #126009#
    if ( bInvalidate )
    {
        InvalidateMe();
        NotifyInvalidSiblings();
    }
    // <--
}

bool SwNodeNum::IsRestart() const
{
    return mbRestart;
}

void SwNodeNum::SetStart(SwNumberTreeNode::tSwNumTreeNumber nStart)
{
    // --> OD 2005-10-19 #126009#
    // - improvement: invalidation only, if <IsRestart()> state changes.
    const bool bInvalidate( mnStart != nStart );
    // <--
    mnStart = nStart;

    // --> OD 2005-10-19 #126009#
    if ( bInvalidate )
    {
        InvalidateMe();
        NotifyInvalidSiblings();
    }
}

bool SwNodeNum::IsCountPhantoms() const
{
    bool bResult = true;

    // --> OD 2006-04-21 #i64311#
    // phantoms aren't counted in consecutive numbering rules
    if ( mpNumRule )
        bResult = !mpNumRule->IsContinusNum() &&
                  mpNumRule->IsCountPhantoms();
    else
    {
        ASSERT( false,
                "<SwNodeNum::IsCountPhantoms(): missing numbering rule - please inform OD" );
    }
    // <--

    return bResult;
}

SwNumberTreeNode::tSwNumTreeNumber SwNodeNum::GetStart() const
{
    tSwNumTreeNumber aResult = 1;

    // --> OD 2005-11-16 #i57919# - consider that start value <USHRT_MAX>
    // indicates, that the numbering is restarted at this node with the
    // start value, which is set at the corresponding numbering level.
    if ( IsRestart() && mnStart != USHRT_MAX )
    // <--
    {
        aResult = mnStart;
    }
    else
    {
        SwNumRule * pRule = GetNumRule();

        if (pRule)
        {
            // --> OD 2006-04-24 #i64311#
            // consider root number tree node
            // --> OD 2006-05-24 #i65705# - correct fix for i64311
            int nLevel = GetParent() ? GetLevel() : 0;
            // <--

            if (nLevel >= 0 && nLevel < MAXLEVEL)
            {
                const SwNumFmt * pFmt = pRule->GetNumFmt( static_cast<USHORT>(nLevel));

                if (pFmt)
                    aResult = pFmt->GetStart();
            }
        }
    }

    return aResult;
}

String SwNodeNum::ToString() const
{
    String aResult("[ ", RTL_TEXTENCODING_ASCII_US);

    if (GetTxtNode())
    {
        char aBuffer[256];

        sprintf(aBuffer, "%p ", GetTxtNode());

        aResult += String(aBuffer, RTL_TEXTENCODING_ASCII_US);
        aResult += String::CreateFromInt32(GetPosition().nNode.GetIndex());
    }
    else
        aResult += String("*", RTL_TEXTENCODING_ASCII_US);

    aResult += String(" ", RTL_TEXTENCODING_ASCII_US);

    unsigned int nLvl = GetLevel();
    aResult += String::CreateFromInt32(nLvl);

    aResult += String(": ", RTL_TEXTENCODING_ASCII_US);

    tNumberVector aNumVector;

    _GetNumberVector(aNumVector, false);

    for (unsigned int n = 0; n < aNumVector.size(); n++)
    {
        if (n > 0)
            aResult += String(", ", RTL_TEXTENCODING_ASCII_US);

        aResult += String::CreateFromInt32(aNumVector[n]);
    }

    if (IsCounted())
//        aResult += String(" counted", RTL_TEXTENCODING_ASCII_US);
        aResult += String(" C", RTL_TEXTENCODING_ASCII_US);

    if (IsRestart())
    {
//        aResult += String(" restart(", RTL_TEXTENCODING_ASCII_US);
        aResult += String(" R(", RTL_TEXTENCODING_ASCII_US);
        aResult += String::CreateFromInt32(GetStart());
        aResult += String(")", RTL_TEXTENCODING_ASCII_US);
    }

    if (! IsValid())
//        aResult += String(" invalid", RTL_TEXTENCODING_ASCII_US);
        aResult += String(" I", RTL_TEXTENCODING_ASCII_US);

    aResult += String(" ]", RTL_TEXTENCODING_ASCII_US);

    return aResult;
}

void SwNodeNum::SetLevel(unsigned int nLevel)
{
    ASSERT( nLevel < MAXLEVEL, "illegal level");

    if (mpParent)
    {
        SwNumRule * pRule = GetNumRule();

        if (pRule != mpNumRule || sal::static_int_cast< int >(nLevel) != GetLevel())
        {
            RemoveMe();

            if (pRule)
                pRule->AddNumber(this, nLevel);
        }
    }
}

// --> OD 2006-03-07 #131436#
void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum& rNodeNum )
{
    SwNodeNum* pRootNode = rNodeNum.GetParent()
                           ? dynamic_cast<SwNodeNum*>(rNodeNum.GetRoot())
                           : &rNodeNum;
    if ( !pRootNode )
    {
        // no root node -> nothing do.
        return;
    }

    // unregister all number tree node entries, which correspond to a text node,
    // about the deletion of the number tree root node.
    _UnregisterMeAndChildrenDueToRootDelete( *pRootNode );
}

void SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete( SwNodeNum& rNodeNum )
{
    const bool bIsPhantom( rNodeNum.IsPhantom() );
    tSwNumberTreeChildren::size_type nAllowedChildCount( 0 );
    bool bDone( false );
    while ( !bDone &&
            rNodeNum.GetChildCount() > nAllowedChildCount )
    {
        SwNodeNum* pChildNode( dynamic_cast<SwNodeNum*>((*rNodeNum.mChildren.begin())) );
        if ( !pChildNode )
        {
            ASSERT( false,
                    "<SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" );
            ++nAllowedChildCount;
            continue;
        }

        // Unregistering the last child of a phantom will destroy the phantom.
        // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to
        // be suppressed.
        if ( bIsPhantom && rNodeNum.GetChildCount() == 1 )
        {
            bDone = true;
        }

        _UnregisterMeAndChildrenDueToRootDelete( *pChildNode );
    }

    if ( !bIsPhantom )
    {
        SwTxtNode* pTxtNode( rNodeNum.GetTxtNode() );
        if ( pTxtNode )
        {
            pTxtNode->UnregisterNumber();
        }
    }
}
// <--
<|endoftext|>


<commit_before>/* libjingle
 * Copyright 2012, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/app/webrtc/jsepsessiondescription.h"

#include "talk/app/webrtc/webrtcsdp.h"
#include "talk/session/media/mediasession.h"
#include "webrtc/base/stringencode.h"

using rtc::scoped_ptr;
using cricket::SessionDescription;

namespace webrtc {

static const char* kSupportedTypes[] = {
    JsepSessionDescription::kOffer,
    JsepSessionDescription::kPrAnswer,
    JsepSessionDescription::kAnswer
};

static bool IsTypeSupported(const std::string& type) {
  bool type_supported = false;
  for (size_t i = 0; i < ARRAY_SIZE(kSupportedTypes); ++i) {
    if (kSupportedTypes[i] == type) {
      type_supported = true;
      break;
    }
  }
  return type_supported;
}

const char SessionDescriptionInterface::kOffer[] = "offer";
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
const char SessionDescriptionInterface::kAnswer[] = "answer";

const int JsepSessionDescription::kDefaultVideoCodecId = 100;
// This is effectively a max value of the frame rate. 30 is default from camera.
const int JsepSessionDescription::kDefaultVideoCodecFramerate = 60;
const char JsepSessionDescription::kDefaultVideoCodecName[] = "VP8";
// Used as default max video codec size before we have it in signaling.
#if defined(ANDROID)
// Limit default max video codec size for Android to avoid
// HW VP8 codec initialization failure for resolution higher than 720p.
const int JsepSessionDescription::kMaxVideoCodecWidth = 1280;
const int JsepSessionDescription::kMaxVideoCodecHeight = 720;
#else
const int JsepSessionDescription::kMaxVideoCodecWidth = 1920;
const int JsepSessionDescription::kMaxVideoCodecHeight = 1080;
#endif
const int JsepSessionDescription::kDefaultVideoCodecPreference = 1;

SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
                                                      const std::string& sdp) {
  return CreateSessionDescription(type, sdp, NULL);
}

SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
                                                      const std::string& sdp,
                                                      SdpParseError* error) {
  if (!IsTypeSupported(type)) {
    return NULL;
  }

  JsepSessionDescription* jsep_desc = new JsepSessionDescription(type);
  if (!jsep_desc->Initialize(sdp, error)) {
    delete jsep_desc;
    return NULL;
  }
  return jsep_desc;
}

JsepSessionDescription::JsepSessionDescription(const std::string& type)
    : type_(type) {
}

JsepSessionDescription::~JsepSessionDescription() {}

bool JsepSessionDescription::Initialize(
    cricket::SessionDescription* description,
    const std::string& session_id,
    const std::string& session_version) {
  if (!description)
    return false;

  session_id_ = session_id;
  session_version_ = session_version;
  description_.reset(description);
  candidate_collection_.resize(number_of_mediasections());
  return true;
}

bool JsepSessionDescription::Initialize(const std::string& sdp,
                                        SdpParseError* error) {
  return SdpDeserialize(sdp, this, error);
}

bool JsepSessionDescription::AddCandidate(
    const IceCandidateInterface* candidate) {
  if (!candidate || candidate->sdp_mline_index() < 0)
    return false;
  size_t mediasection_index = 0;
  if (!GetMediasectionIndex(candidate, &mediasection_index)) {
    return false;
  }
  if (mediasection_index >= number_of_mediasections())
    return false;
  const std::string content_name =
      description_->contents()[mediasection_index].name;
  const cricket::TransportInfo* transport_info =
      description_->GetTransportInfoByName(content_name);
  if (!transport_info) {
    return false;
  }

  cricket::Candidate updated_candidate = candidate->candidate();
  if (updated_candidate.username().empty()) {
    updated_candidate.set_username(transport_info->description.ice_ufrag);
  }
  if (updated_candidate.password().empty()) {
    updated_candidate.set_password(transport_info->description.ice_pwd);
  }

  scoped_ptr<JsepIceCandidate> updated_candidate_wrapper(
      new JsepIceCandidate(candidate->sdp_mid(),
                           static_cast<int>(mediasection_index),
                           updated_candidate));
  if (!candidate_collection_[mediasection_index].HasCandidate(
          updated_candidate_wrapper.get()))
    candidate_collection_[mediasection_index].add(
        updated_candidate_wrapper.release());

  return true;
}

size_t JsepSessionDescription::number_of_mediasections() const {
  if (!description_)
    return 0;
  return description_->contents().size();
}

const IceCandidateCollection* JsepSessionDescription::candidates(
    size_t mediasection_index) const {
  if (mediasection_index >= candidate_collection_.size())
    return NULL;
  return &candidate_collection_[mediasection_index];
}

bool JsepSessionDescription::ToString(std::string* out) const {
  if (!description_ || !out)
    return false;
  *out = SdpSerialize(*this);
  return !out->empty();
}

bool JsepSessionDescription::GetMediasectionIndex(
    const IceCandidateInterface* candidate,
    size_t* index) {
  if (!candidate || !index) {
    return false;
  }
  *index = static_cast<size_t>(candidate->sdp_mline_index());
  if (description_ && !candidate->sdp_mid().empty()) {
    bool found = false;
    // Try to match the sdp_mid with content name.
    for (size_t i = 0; i < description_->contents().size(); ++i) {
      if (candidate->sdp_mid() == description_->contents().at(i).name) {
        *index = i;
        found = true;
        break;
      }
    }
    if (!found) {
      // If the sdp_mid is presented but we can't find a match, we consider
      // this as an error.
      return false;
    }
  }
  return true;
}

}  // namespace webrtc
<commit_msg>Allow 720x1280 frames encoding on Android.<commit_after>/* libjingle
 * Copyright 2012, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/app/webrtc/jsepsessiondescription.h"

#include "talk/app/webrtc/webrtcsdp.h"
#include "talk/session/media/mediasession.h"
#include "webrtc/base/stringencode.h"

using rtc::scoped_ptr;
using cricket::SessionDescription;

namespace webrtc {

static const char* kSupportedTypes[] = {
    JsepSessionDescription::kOffer,
    JsepSessionDescription::kPrAnswer,
    JsepSessionDescription::kAnswer
};

static bool IsTypeSupported(const std::string& type) {
  bool type_supported = false;
  for (size_t i = 0; i < ARRAY_SIZE(kSupportedTypes); ++i) {
    if (kSupportedTypes[i] == type) {
      type_supported = true;
      break;
    }
  }
  return type_supported;
}

const char SessionDescriptionInterface::kOffer[] = "offer";
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
const char SessionDescriptionInterface::kAnswer[] = "answer";

const int JsepSessionDescription::kDefaultVideoCodecId = 100;
// This is effectively a max value of the frame rate. 30 is default from camera.
const int JsepSessionDescription::kDefaultVideoCodecFramerate = 60;
const char JsepSessionDescription::kDefaultVideoCodecName[] = "VP8";
// Used as default max video codec size before we have it in signaling.
#if defined(ANDROID)
// Limit default max video codec size for Android to avoid
// HW VP8 codec initialization failure for resolutions higher
// than 1280x720 or 720x1280.
const int JsepSessionDescription::kMaxVideoCodecWidth = 1280;
const int JsepSessionDescription::kMaxVideoCodecHeight = 1280;
#else
const int JsepSessionDescription::kMaxVideoCodecWidth = 1920;
const int JsepSessionDescription::kMaxVideoCodecHeight = 1080;
#endif
const int JsepSessionDescription::kDefaultVideoCodecPreference = 1;

SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
                                                      const std::string& sdp) {
  return CreateSessionDescription(type, sdp, NULL);
}

SessionDescriptionInterface* CreateSessionDescription(const std::string& type,
                                                      const std::string& sdp,
                                                      SdpParseError* error) {
  if (!IsTypeSupported(type)) {
    return NULL;
  }

  JsepSessionDescription* jsep_desc = new JsepSessionDescription(type);
  if (!jsep_desc->Initialize(sdp, error)) {
    delete jsep_desc;
    return NULL;
  }
  return jsep_desc;
}

JsepSessionDescription::JsepSessionDescription(const std::string& type)
    : type_(type) {
}

JsepSessionDescription::~JsepSessionDescription() {}

bool JsepSessionDescription::Initialize(
    cricket::SessionDescription* description,
    const std::string& session_id,
    const std::string& session_version) {
  if (!description)
    return false;

  session_id_ = session_id;
  session_version_ = session_version;
  description_.reset(description);
  candidate_collection_.resize(number_of_mediasections());
  return true;
}

bool JsepSessionDescription::Initialize(const std::string& sdp,
                                        SdpParseError* error) {
  return SdpDeserialize(sdp, this, error);
}

bool JsepSessionDescription::AddCandidate(
    const IceCandidateInterface* candidate) {
  if (!candidate || candidate->sdp_mline_index() < 0)
    return false;
  size_t mediasection_index = 0;
  if (!GetMediasectionIndex(candidate, &mediasection_index)) {
    return false;
  }
  if (mediasection_index >= number_of_mediasections())
    return false;
  const std::string content_name =
      description_->contents()[mediasection_index].name;
  const cricket::TransportInfo* transport_info =
      description_->GetTransportInfoByName(content_name);
  if (!transport_info) {
    return false;
  }

  cricket::Candidate updated_candidate = candidate->candidate();
  if (updated_candidate.username().empty()) {
    updated_candidate.set_username(transport_info->description.ice_ufrag);
  }
  if (updated_candidate.password().empty()) {
    updated_candidate.set_password(transport_info->description.ice_pwd);
  }

  scoped_ptr<JsepIceCandidate> updated_candidate_wrapper(
      new JsepIceCandidate(candidate->sdp_mid(),
                           static_cast<int>(mediasection_index),
                           updated_candidate));
  if (!candidate_collection_[mediasection_index].HasCandidate(
          updated_candidate_wrapper.get()))
    candidate_collection_[mediasection_index].add(
        updated_candidate_wrapper.release());

  return true;
}

size_t JsepSessionDescription::number_of_mediasections() const {
  if (!description_)
    return 0;
  return description_->contents().size();
}

const IceCandidateCollection* JsepSessionDescription::candidates(
    size_t mediasection_index) const {
  if (mediasection_index >= candidate_collection_.size())
    return NULL;
  return &candidate_collection_[mediasection_index];
}

bool JsepSessionDescription::ToString(std::string* out) const {
  if (!description_ || !out)
    return false;
  *out = SdpSerialize(*this);
  return !out->empty();
}

bool JsepSessionDescription::GetMediasectionIndex(
    const IceCandidateInterface* candidate,
    size_t* index) {
  if (!candidate || !index) {
    return false;
  }
  *index = static_cast<size_t>(candidate->sdp_mline_index());
  if (description_ && !candidate->sdp_mid().empty()) {
    bool found = false;
    // Try to match the sdp_mid with content name.
    for (size_t i = 0; i < description_->contents().size(); ++i) {
      if (candidate->sdp_mid() == description_->contents().at(i).name) {
        *index = i;
        found = true;
        break;
      }
    }
    if (!found) {
      // If the sdp_mid is presented but we can't find a match, we consider
      // this as an error.
      return false;
    }
  }
  return true;
}

}  // namespace webrtc
<|endoftext|>