summaryrefslogtreecommitdiffstats
path: root/src/spreadsheet/factory_pivot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/spreadsheet/factory_pivot.cpp')
-rw-r--r--src/spreadsheet/factory_pivot.cpp303
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: */