2005-08-04 22:42:30 +02:00
|
|
|
#ifndef ARABICA_XPATHIC_XPATH_UNION_HPP
|
|
|
|
#define ARABICA_XPATHIC_XPATH_UNION_HPP
|
|
|
|
|
|
|
|
#include "xpath_value.hpp"
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XPath
|
|
|
|
{
|
2005-08-22 17:04:27 +02:00
|
|
|
namespace impl
|
|
|
|
{
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2007-12-21 16:56:04 +01:00
|
|
|
class UnionExpression : public BinaryExpression<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 12:13:05 +02:00
|
|
|
typedef BinaryExpression<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-23 23:37:24 +02:00
|
|
|
UnionExpression(XPathExpression_impl<string_type, string_adaptor>* lhs,
|
|
|
|
XPathExpression_impl<string_type, string_adaptor>* rhs) :
|
2005-08-17 12:13:05 +02:00
|
|
|
BinaryExpression<string_type, string_adaptor>(lhs, rhs) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return NODE_SET; }
|
|
|
|
|
2007-10-22 19:42:50 +02:00
|
|
|
virtual XPathValue<string_type, string_adaptor> evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2007-10-22 19:42:50 +02:00
|
|
|
XPathValue<string_type, string_adaptor> p1 = baseT::lhs()->evaluate(context, executionContext);
|
|
|
|
if(p1.type() != NODE_SET)
|
2005-08-04 22:42:30 +02:00
|
|
|
throw RuntimeException("Union operator joins node-sets. First argument is not a node-set.");
|
2007-10-22 19:42:50 +02:00
|
|
|
XPathValue<string_type, string_adaptor> p2 = baseT::rhs()->evaluate(context, executionContext);
|
|
|
|
if(p2.type() != NODE_SET)
|
2005-08-16 18:04:24 +02:00
|
|
|
throw RuntimeException("Union operator joins node-sets. Second argument is not a node-set.");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-10-22 19:42:50 +02:00
|
|
|
NodeSet<string_type, string_adaptor> ns1(p1.asNodeSet());
|
|
|
|
NodeSet<string_type, string_adaptor> ns2(p2.asNodeSet());
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
// do the obvious optimizations
|
|
|
|
if(ns1.empty())
|
|
|
|
return wrap(ns2);
|
|
|
|
if(ns2.empty())
|
|
|
|
return wrap(ns1);
|
|
|
|
|
2007-07-19 19:01:31 +02:00
|
|
|
ns1.insert(ns1.end()-1, ns2.begin(), ns2.end());
|
2005-08-04 22:42:30 +02:00
|
|
|
ns1.to_document_order();
|
|
|
|
|
2007-07-19 19:01:31 +02:00
|
|
|
return wrap(ns1);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
|
|
|
|
private:
|
2007-10-22 19:42:50 +02:00
|
|
|
XPathValue<string_type, string_adaptor> wrap(const NodeSet<string_type, string_adaptor>& ns) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2007-10-22 19:42:50 +02:00
|
|
|
return XPathValue<string_type, string_adaptor>(new NodeSetValue<string_type, string_adaptor>(ns));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // wrap
|
|
|
|
}; // UnionExpression
|
|
|
|
|
2005-08-22 17:04:27 +02:00
|
|
|
} // namespace impl
|
2005-08-04 22:42:30 +02:00
|
|
|
} // namespace XPath
|
|
|
|
} // namespace Arabica
|
|
|
|
#endif
|