/* Copyright (c) 2008-2009, AbiSource Corporation B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name of AbiSource Corporation B.V. nor the * names of other contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY ABISOURCE CORPORATION B.V. AND OTHER * CONTRIBUTORS ''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 ABISOURCE * CORPORATION B.V OR OTHER CONTRIBUTORS 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. */ #ifndef __SOA__ #define __SOA__ #ifdef _MSC_VER #include "msc_stdint.h" #else #include #endif #include #include #include #include #include "soa_types.h" #include "soa_result.h" namespace soa { class function_arg { public: function_arg(const std::string& n, Type t) : name_(n), type_(t) {} virtual ~function_arg() {} const std::string& name() const { return name_; } Type type() const { return type_; } virtual bool type_props() const { return false; } virtual std::string props() const { return ""; } // FIXME: returning an std::string is inefficient for large blocks of // data; we should make it a boost::shared_ptr virtual std::string str() const = 0; private: std::string name_; Type type_; }; class function_arg_string : public function_arg { public: function_arg_string(const std::string& n, const std::string& value) : function_arg(n, STRING_TYPE), value_(value) {} virtual std::string str() const { return value_; } private: std::string value_; }; class function_arg_int : public function_arg { public: function_arg_int(const std::string& n, int64_t value) : function_arg(n, INT_TYPE), value_(value) {} virtual std::string str() const { try { return boost::lexical_cast(value_); } catch (boost::bad_lexical_cast &) { return "0"; } } private: int64_t value_; }; class function_arg_bool : public function_arg { public: function_arg_bool(const std::string& n, bool value) : function_arg(n, BOOL_TYPE), value_(value) {} virtual std::string str() const { return value_ ? "true" : "false"; } private: bool value_; }; class function_arg_base64bin : public function_arg { public: function_arg_base64bin(Base64Bin value) : function_arg(value.name(), BASE64BIN_TYPE), value_(value) {} virtual std::string str() const { return value_.value(); } private: Base64Bin value_; }; class function_arg_array : public function_arg { public: // TODO: automatically deduce the type of the array function_arg_array(const std::string& n, ArrayPtr value, Type element_type) : function_arg(n, ARRAY_TYPE), value_(value), element_type_(element_type) {} virtual bool type_props() const { return true; } virtual std::string props() const { if (value_) return "SOAP-ENC:arrayType=\"" + soap_type(element_type_) + "[" + boost::lexical_cast(value_->size()) + "]\"" + " " + "SOAP-ENC:offset=\"[0]\""; return "SOAP-ENC:arrayType=\"xsd:anyType[0]\" xsi:nil=\"true\""; } virtual std::string str() const { std::string ret = "\n"; if (!value_) return ret; for (size_t i = 0; i < value_->size(); i++) { GenericPtr val = value_->operator[](i); if (!val) continue; // TODO: generalize this; for now, we only support arrays of integers IntPtr val_int = boost::dynamic_pointer_cast(val); if (!val_int) continue; function_arg_int arg(val->name(), val_int->value()); ret += "<" + arg.name() + " " + "xsi:type=\"" + soap_type(arg.type()) + "\"" + ">" + arg.str() + "\n"; } return ret; } private: ArrayPtr value_; Type element_type_; }; class function_call { public: function_call() {} function_call(const std::string& req, const std::string& resp) : request_(req), response_(resp) {} function_call& operator()(std::string name, const char* value) { args.push_back(boost::shared_ptr(new function_arg_string(name, value))); return *this; } function_call& operator()(std::string name, std::string value) { args.push_back(boost::shared_ptr(new function_arg_string(name, value))); return *this; } function_call& operator()(std::string name, int64_t value) { args.push_back(boost::shared_ptr(new function_arg_int(name, value))); return *this; } function_call& operator()(std::string name, bool value) { args.push_back(boost::shared_ptr(new function_arg_bool(name, value))); return *this; } function_call& operator()(Base64Bin value) { args.push_back(boost::shared_ptr(new function_arg_base64bin(value))); return *this; } function_call& operator()(std::string name, ArrayPtr value, Type type) { args.push_back(boost::shared_ptr(new function_arg_array(name, value, type))); return *this; } const std::string& request() const { return request_; } const std::string& response() const { return response_; } void add_arg(boost::shared_ptr arg) { args.push_back(arg); } std::string str() const { std::string ret; // TODO: XML escape args/values for (std::vector< boost::shared_ptr >::const_iterator cit = args.begin(); cit != args.end(); cit++) { const function_arg& arg = **cit; ret += "<" + arg.name() + " " + "xsi:type=\"" + soap_type(arg.type()) + "\"" + (arg.type_props() ? " " + arg.props() : "") + ">" + arg.str() + "\n"; } return ret; } private: std::string request_; std::string response_; std::vector< boost::shared_ptr > args; }; typedef boost::shared_ptr function_call_ptr; class header { public: std::string str() const { return ""; } }; class body { public: body(const std::string& ns_ref_) : ns_ref(ns_ref_) {} body(const std::string& ns_ref_, const function_call& fc) : ns_ref(ns_ref_), fc_(fc) {} const function_call& function() const { return fc_; } void set_function(function_call fc) { fc_ = fc; } std::string str() const { return "\n" \ "<" + ns_ref + ":" + fc_.request() + ">\n" + fc_.str() + "\n" \ "\n"; } private: std::string ns_ref; function_call fc_; }; class method_invocation { public: method_invocation(const std::string& custom_ns) : custom_ns_(custom_ns), custom_ns_ref_("nsref"), body_(custom_ns_ref_) {} method_invocation(const std::string& custom_ns, function_call fc) : custom_ns_(custom_ns), custom_ns_ref_("nsref"), body_(custom_ns_ref_, fc) {} const function_call& function() const { return body_.function(); } std::string str() const { return "\n" \ "\n" + header_.str() + body_.str() + ""; } private: std::string default_namespaces() const { return "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" \ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" \ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" \ " xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\""; } std::string encoding_style() const { return "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""; } std::string input_name_; std::string output_name_; std::string custom_ns_; std::string custom_ns_ref_; header header_; body body_; }; } #endif /* __SOA__ */