text: /** 
   * @file ServiceFactory.h
   * 
   * @author John Wason, PhD
   * 
   * @copyright Copyright 2011-2020 Wason Technology, LLC
   *
   * @par License
   * Software License Agreement (Apache License)
   * @par
   * Licensed 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
   * @par
   * http://www.apache.org/licenses/LICENSE-2.0
   * @par
   * 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.
   */
  
  #pragma once
  
  #include "RobotRaconteur/DataTypes.h"
  #include "RobotRaconteur/Message.h"
  #include "RobotRaconteur/ServiceDefinition.h"
  
  namespace RobotRaconteur
  {
  
  	class ROBOTRACONTEUR_CORE_API StructureStub;
  	class ROBOTRACONTEUR_CORE_API ServiceStub;
  	
  	class ROBOTRACONTEUR_CORE_API ClientContext;
  	
  	class ROBOTRACONTEUR_CORE_API RobotRaconteurNode;
  	
  	/**
  	 * @brief Base class for service factories
  	 * 
  	 * Service factories are generated by RobotRaconteurGen for static 
  	 * such as languages C++, Java, and C\#,
  	 * or dynamically generated by dynamic languages such as Python and MATLAB.
  	 * Service factories must be registered with the node using RobotRaconteurNodeSetup,
  	 * ClientNodeSetup, ServerNodeSetup, or RobotRaconteurNode::RegisterServiceType().
  	 * 
  	 * Each service definition corresponds to one service factory. Service factories
  	 * are not typically accessed by the user once registered.
  	 * 
  	 */
  	class ROBOTRACONTEUR_CORE_API ServiceFactory
  	{
  
  	public:
  
  		RR_SHARED_PTR<RobotRaconteurNode> GetNode();
  
  		void SetNode(RR_SHARED_PTR<RobotRaconteurNode> node);
  
  		virtual ~ServiceFactory() {}
  
  		/**
  		 * @brief Returns the name of the service
  		 * 
  		 * @return std::string The name of the service
  		 */
  		virtual std::string GetServiceName()=0;
  
  		/**
  		 * @brief Return the service definition string used to generate the service factory
  		 * 
  		 * @return std::string The service definition as a string
  		 */
  		virtual std::string DefString()=0;
  
  		virtual RR_SHARED_PTR<StructureStub> FindStructureStub(boost::string_ref s)=0;
  		
  		virtual RR_INTRUSIVE_PTR<MessageElementNestedElementList> PackStructure(RR_INTRUSIVE_PTR<RRStructure> structin)=0;
  				
  		virtual RR_INTRUSIVE_PTR<RRValue> UnpackStructure(RR_INTRUSIVE_PTR<MessageElementNestedElementList> mstructin)=0; 
  
  		virtual RR_INTRUSIVE_PTR<MessageElementNestedElementList> PackPodArray(RR_INTRUSIVE_PTR<RRPodBaseArray> structure)=0;
  
  		virtual RR_INTRUSIVE_PTR<RRPodBaseArray> UnpackPodArray(RR_INTRUSIVE_PTR<MessageElementNestedElementList> structure)=0;
  
  		virtual RR_INTRUSIVE_PTR<MessageElementNestedElementList> PackPodMultiDimArray(RR_INTRUSIVE_PTR<RRPodBaseMultiDimArray> structure)=0;
  
  		virtual RR_INTRUSIVE_PTR<RRPodBaseMultiDimArray> UnpackPodMultiDimArray(RR_INTRUSIVE_PTR<MessageElementNestedElementList> structure)=0;
  
  		virtual RR_INTRUSIVE_PTR<MessageElementNestedElementList> PackNamedArray(RR_INTRUSIVE_PTR<RRNamedBaseArray> structure) = 0;
  
  		virtual RR_INTRUSIVE_PTR<RRNamedBaseArray> UnpackNamedArray(RR_INTRUSIVE_PTR<MessageElementNestedElementList> structure) = 0;
  
  		virtual RR_INTRUSIVE_PTR<MessageElementNestedElementList> PackNamedMultiDimArray(RR_INTRUSIVE_PTR<RRNamedBaseMultiDimArray> structure) = 0;
  
  		virtual RR_INTRUSIVE_PTR<RRNamedBaseMultiDimArray> UnpackNamedMultiDimArray(RR_INTRUSIVE_PTR<MessageElementNestedElementList> structure) = 0;
  
  		virtual RR_SHARED_PTR<ServiceStub> CreateStub(boost::string_ref objecttype, boost::string_ref path, RR_SHARED_PTR<ClientContext> context)=0;
  
  		/**
  		 * @brief Return the parsed ServiceDefinition
  		 * 
  		 * @return RR_SHARED_PTR<ServiceDefinition> The service definition after parsing
  		 */
  		virtual RR_SHARED_PTR<ServiceDefinition> ServiceDef();
  		
  		virtual std::string RemovePath(boost::string_ref path);
  
  		virtual void DownCastAndThrowException(RobotRaconteurException& exp)=0;
  
  		virtual RR_SHARED_PTR<RobotRaconteurException> DownCastException(RR_SHARED_PTR<RobotRaconteurException> exp)=0;
  
  	private:
  		RR_SHARED_PTR<ServiceDefinition> sdef;
  		RR_WEAK_PTR<RobotRaconteurNode> node;
  	};
   
  	/**
  	 * @brief Dynamic service factory base class
  	 * 
  	 * Dynamic service factories are used to automatically generate service definitions
  	 * as needed. They are using with dynamic languages such as Python and MATLAB with
  	 * service definitions pulled by the client.
  	 * 
  	 */
  	class ROBOTRACONTEUR_CORE_API DynamicServiceFactory
  	{
  	public:
  
  		virtual ~DynamicServiceFactory() {}
  
  		/**
  		 * @brief Override to return service factory from a service definition string
  		 * 
  		 * Factory should return a service factory implementing the provided service definition string.
  		 * 
  		 * @param def The service definiton as a string
  		 * @return RR_SHARED_PTR<ServiceFactory> The generated service factory
  		 */
  		virtual RR_SHARED_PTR<ServiceFactory> CreateServiceFactory(boost::string_ref def) = 0;
  
  		/**
  		 * @brief Override to return collection of service factories from a collection of service definition strings
  		 * 
  		 * Factory should return a vector service factory implementing the provided vector of service definition string.
  		 * Clients will provide related service definitions at the same time so they can be verified.
  		 * 
  		 * @param def The collection of service definiton strings
  		 * @return RR_SHARED_PTR<ServiceFactory> The generated service factories
  		 */
  		virtual std::vector<RR_SHARED_PTR<ServiceFactory> > CreateServiceFactories(const std::vector<std::string>& def) = 0;
  	};
  
  }
  