blob: 97294154f526662fb1e10ad6c406af8e70cb9d77 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
#ifndef __TEST_DSE_LINE_STRING_HPP__
#define __TEST_DSE_LINE_STRING_HPP__
#include "test_utils.hpp"
#include "dse_point.hpp"
#include <algorithm>
namespace test { namespace driver { namespace values { namespace dse {
/**
* DSE line string wrapped value
*/
class LineString : public Comparable<LineString> {
public:
typedef Object<DseLineString, dse_line_string_free> Native;
typedef Object<DseLineStringIterator, dse_line_string_iterator_free> Iterator;
typedef std::string ConvenienceType;
typedef std::vector<Point> ValueType;
LineString() {}
/**
* @throws Point::Exception
*/
LineString(const ConvenienceType& value) {
// Strip all value information markup for a DSE line string
std::string value_trim = Utils::trim(Utils::to_lower(value));
std::string line_string_value = Utils::replace_all(value_trim, "linestring empty", "");
line_string_value = Utils::replace_all(line_string_value, "linestring", "");
line_string_value = Utils::replace_all(line_string_value, "(", "");
line_string_value = Utils::trim(Utils::replace_all(line_string_value, ")", ""));
// Make sure the DSE line string value is valid and convert into wrapped object
std::vector<std::string> points = Utils::explode(line_string_value, ',');
for (std::vector<std::string>::const_iterator iterator = points.begin();
iterator < points.end(); ++iterator) {
Point point(*iterator);
points_.push_back(point);
}
}
/**
* Constructor using vector of points
*
* @param points Vector of points
*/
LineString(const std::vector<Point>& points)
: points_(points) {}
void append(Collection collection) {
Native line_string = to_native();
ASSERT_EQ(CASS_OK, cass_collection_append_dse_line_string(collection.get(), line_string.get()));
}
std::string cql_type() const { return "'LineStringType'"; }
std::string cql_value() const {
if (points_.empty()) {
return "'LINESTRING EMPTY'";
}
return "'LINESTRING(" + str() + ")'";
}
/**
* Comparison operation for driver value DSE line string. This comparison
* is performed in lexicographical order.
*
* @param rhs Right hand side to compare
* @return -1 if LHS < RHS, 1 if LHS > RHS, and 0 if equal
*/
int compare(const std::vector<Point>& rhs) const {
// Ensure they are the same size
if (points_.size() < rhs.size()) return -1;
if (points_.size() > rhs.size()) return 1;
// Sort the points for lexicographical comparison
std::vector<Point> lhs_sorted(points_);
std::vector<Point> rhs_sorted(rhs);
std::sort(lhs_sorted.begin(), lhs_sorted.end());
std::sort(rhs_sorted.begin(), rhs_sorted.end());
// Iterate and compare
for (size_t i = 0; i < lhs_sorted.size(); ++i) {
int comparison = lhs_sorted[i].compare(rhs_sorted[i]);
if (comparison != 0) return comparison;
}
return 0;
}
/**
* Comparison operation for driver value DSE line string. This comparison
* is performed in lexicographical order.
*
* @param rhs Right hand side to compare
* @return -1 if LHS < RHS, 1 if LHS > RHS, and 0 if equal
*/
int compare(const LineString& rhs) const { return compare(rhs.points_); }
void initialize(const CassValue* value) {
// Get the line string from the value
Iterator iterator(dse_line_string_iterator_new());
ASSERT_EQ(CASS_OK, dse_line_string_iterator_reset(iterator.get(), value))
<< "Unable to Reset DSE Line String Iterator: Invalid error code returned";
assign_points(iterator);
}
void set(Tuple tuple, size_t index) {
Native line_string = to_native();
ASSERT_EQ(CASS_OK, cass_tuple_set_dse_line_string(tuple.get(), index, line_string.get()));
}
void set(UserType user_type, const std::string& name) {
Native line_string = to_native();
ASSERT_EQ(CASS_OK, cass_user_type_set_dse_line_string_by_name(user_type.get(), name.c_str(),
line_string.get()));
}
/**
* Get the size of the line string
*
* @return The number of points in the line string
*/
size_t size() const { return points_.size(); }
void statement_bind(Statement statement, size_t index) {
Native line_string = to_native();
ASSERT_EQ(CASS_OK,
cass_statement_bind_dse_line_string(statement.get(), index, line_string.get()));
}
void statement_bind(Statement statement, const std::string& name) {
Native line_string = to_native();
ASSERT_EQ(CASS_OK, cass_statement_bind_dse_line_string_by_name(statement.get(), name.c_str(),
line_string.get()));
}
std::string str() const {
std::stringstream line_string;
for (std::vector<Point>::const_iterator iterator = points_.begin(); iterator < points_.end();
++iterator) {
line_string << (*iterator).str();
// Add a comma separation to the line string (unless the last element)
if ((iterator + 1) != points_.end()) {
line_string << ", ";
}
}
return line_string.str();
}
static std::string supported_server_version() { return "5.0.0"; }
Native to_native() const {
// Create the native line string object
Native line_string = dse_line_string_new();
// Ensure the line string has sufficient point(s)
if (points_.size() > 0) {
// Initialize the line string
dse_line_string_reserve(line_string.get(), static_cast<cass_uint32_t>(points_.size()));
// Add all the points to the native driver object
for (std::vector<Point>::const_iterator iterator = points_.begin(); iterator < points_.end();
++iterator) {
Point::PointType point = (*iterator).value();
EXPECT_EQ(CASS_OK, dse_line_string_add_point(line_string.get(), point.x, point.y))
<< "Unable to Add DSE Point to DSE Line String: Invalid error code returned";
}
EXPECT_EQ(CASS_OK, dse_line_string_finish(line_string.get()))
<< "Unable to Complete DSE Line String: Invalid error code returned";
}
// Return the generated line string
return line_string;
}
ValueType value() const { return points_; }
CassValueType value_type() const { return CASS_VALUE_TYPE_CUSTOM; }
private:
/**
* DSE Points used in the DSE line string
*/
std::vector<Point> points_;
/**
* Assign the points from the native iterator
*
* @param iterator Native driver iterator
*/
void assign_points(Iterator iterator) {
// Get the number of points in the line string
cass_uint32_t size = dse_line_string_iterator_num_points(iterator.get());
// Utilize the iterator to assign the points from the line string
for (cass_uint32_t i = 0; i < size; ++i) {
Point::PointType point = { 0.0, 0.0 };
ASSERT_EQ(CASS_OK, dse_line_string_iterator_next_point(iterator.get(), &point.x, &point.y))
<< "Unable to Get DSE Point from DSE Line String: Invalid error code returned";
points_.push_back(Point(point));
}
}
};
inline std::ostream& operator<<(std::ostream& os, const LineString& line_string) {
os << line_string.cql_value();
return os;
}
}}}} // namespace test::driver::values::dse
#endif // __TEST_DSE_LINE_STRING_HPP__