diff options
Diffstat (limited to 'src/spreadsheet/factory_pivot.cpp')
-rw-r--r-- | src/spreadsheet/factory_pivot.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/src/spreadsheet/factory_pivot.cpp b/src/spreadsheet/factory_pivot.cpp new file mode 100644 index 0000000..2761da5 --- /dev/null +++ b/src/spreadsheet/factory_pivot.cpp @@ -0,0 +1,303 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "factory_pivot.hpp" + +#include "orcus/string_pool.hpp" +#include "orcus/exception.hpp" + +#include <sstream> +#include <iostream> +#include <cassert> + +namespace orcus { namespace spreadsheet { + +class import_pc_field_group : public iface::import_pivot_cache_field_group +{ + using range_grouping_type = pivot_cache_group_data_t::range_grouping_type; + + document& m_doc; + pivot_cache_field_t& m_parent_field; + std::unique_ptr<pivot_cache_group_data_t> m_data; + pivot_cache_item_t m_current_field_item; + +private: + std::string_view intern(std::string_view s) + { + return m_doc.get_string_pool().intern(s).first; + } + + range_grouping_type& get_range_grouping() + { + if (!m_data->range_grouping) + m_data->range_grouping = range_grouping_type(); + + return *m_data->range_grouping; + } + +public: + import_pc_field_group(document& doc, pivot_cache_field_t& parent, size_t base_index) : + m_doc(doc), + m_parent_field(parent), + m_data(std::make_unique<pivot_cache_group_data_t>(base_index)) {} + + ~import_pc_field_group() override {} + + void link_base_to_group_items(size_t group_item_index) override + { + pivot_cache_indices_t& b2g = m_data->base_to_group_indices; + b2g.push_back(group_item_index); + } + + void set_field_item_string(std::string_view value) override + { + m_current_field_item.type = pivot_cache_item_t::item_type::character; + m_current_field_item.value = intern(value); + } + + void set_field_item_numeric(double v) override + { + m_current_field_item.type = pivot_cache_item_t::item_type::numeric; + m_current_field_item.value = v; + } + + void commit_field_item() override + { + m_data->items.push_back(std::move(m_current_field_item)); + } + + void set_range_grouping_type(pivot_cache_group_by_t group_by) override + { + get_range_grouping().group_by = group_by; + } + + void set_range_auto_start(bool b) override + { + get_range_grouping().auto_start = b; + } + + void set_range_auto_end(bool b) override + { + get_range_grouping().auto_end = b; + } + + void set_range_start_number(double v) override + { + get_range_grouping().start = v; + } + + void set_range_end_number(double v) override + { + get_range_grouping().end = v; + } + + void set_range_start_date(const date_time_t& dt) override + { + get_range_grouping().start_date = dt; + } + + void set_range_end_date(const date_time_t& dt) override + { + get_range_grouping().end_date = dt; + } + + void set_range_interval(double v) override + { + get_range_grouping().interval = v; + } + + void commit() override + { + m_parent_field.group_data = std::move(m_data); + } +}; + +std::string_view import_pivot_cache_def::intern(std::string_view s) +{ + return m_doc.get_string_pool().intern(s).first; +} + +import_pivot_cache_def::import_pivot_cache_def(document& doc) : m_doc(doc) {} + +import_pivot_cache_def::~import_pivot_cache_def() {} + +void import_pivot_cache_def::create_cache(pivot_cache_id_t cache_id) +{ + m_src_type = unknown; + m_cache = std::make_unique<pivot_cache>(cache_id, m_doc.get_string_pool()); +} + +void import_pivot_cache_def::set_worksheet_source(std::string_view ref, std::string_view sheet_name) +{ + assert(m_cache); + + const ixion::formula_name_resolver* resolver = + m_doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + assert(resolver); + + m_src_type = worksheet; + m_src_sheet_name = intern(sheet_name); + + ixion::formula_name_t fn = resolver->resolve(ref, ixion::abs_address_t(0,0,0)); + + if (fn.type != ixion::formula_name_t::range_reference) + { + std::ostringstream os; + os << "'" << ref << "' is not a valid range."; + throw xml_structure_error(os.str()); + } + + m_src_range = std::get<ixion::range_t>(fn.value).to_abs(ixion::abs_address_t(0,0,0)); +} + +void import_pivot_cache_def::set_worksheet_source(std::string_view table_name) +{ + assert(m_cache); + + m_src_table_name = intern(table_name); +} + +void import_pivot_cache_def::set_field_count(size_t n) +{ + m_current_fields.reserve(n); +} + +void import_pivot_cache_def::set_field_name(std::string_view name) +{ + m_current_field.name = intern(name); +} + +iface::import_pivot_cache_field_group* import_pivot_cache_def::start_field_group(size_t base_index) +{ + m_current_field_group = + std::make_unique<import_pc_field_group>(m_doc, m_current_field, base_index); + + return m_current_field_group.get(); +} + +void import_pivot_cache_def::set_field_min_value(double v) +{ + m_current_field.min_value = v; +} + +void import_pivot_cache_def::set_field_max_value(double v) +{ + m_current_field.max_value = v; +} + +void import_pivot_cache_def::set_field_min_date(const date_time_t& dt) +{ + m_current_field.min_date = dt; +} + +void import_pivot_cache_def::set_field_max_date(const date_time_t& dt) +{ + m_current_field.max_date = dt; +} + +void import_pivot_cache_def::commit_field() +{ + m_current_fields.push_back(std::move(m_current_field)); +} + +void import_pivot_cache_def::set_field_item_string(std::string_view value) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::character; + m_current_field_item.value = intern(value); +} + +void import_pivot_cache_def::set_field_item_numeric(double v) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::numeric; + m_current_field_item.value = v; +} + +void import_pivot_cache_def::set_field_item_date_time(const date_time_t& dt) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::date_time; + m_current_field_item.value = dt; +} + +void import_pivot_cache_def::set_field_item_error(error_value_t ev) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::error; + m_current_field_item.value = ev; +} + +void import_pivot_cache_def::commit_field_item() +{ + m_current_field.items.push_back(std::move(m_current_field_item)); +} + +void import_pivot_cache_def::commit() +{ + m_cache->insert_fields(std::move(m_current_fields)); + assert(m_current_fields.empty()); + + if (!m_src_table_name.empty()) + { + m_doc.get_pivot_collection().insert_worksheet_cache( + m_src_table_name, std::move(m_cache)); + return; + } + + m_doc.get_pivot_collection().insert_worksheet_cache( + m_src_sheet_name, m_src_range, std::move(m_cache)); +} + +import_pivot_cache_records::import_pivot_cache_records(document& doc) : + m_doc(doc), m_cache(nullptr) {} + +import_pivot_cache_records::~import_pivot_cache_records() {} + +void import_pivot_cache_records::set_cache(pivot_cache* p) +{ + m_cache = p; +} + +void import_pivot_cache_records::set_record_count(size_t n) +{ + m_records.reserve(n); +} + +void import_pivot_cache_records::append_record_value_numeric(double v) +{ + m_current_record.emplace_back(v); +} + +void import_pivot_cache_records::append_record_value_character(std::string_view s) +{ + m_current_record.emplace_back(s); +} + +void import_pivot_cache_records::append_record_value_shared_item(size_t index) +{ + m_current_record.emplace_back(index); +} + +void import_pivot_cache_records::commit_record() +{ + if (!m_cache) + { + m_current_record.clear(); + return; + } + + m_records.push_back(std::move(m_current_record)); +} + +void import_pivot_cache_records::commit() +{ + if (!m_cache) + return; + + m_cache->insert_records(std::move(m_records)); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |