## 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.

// This file automatically generated by:
//   $version
//   $now
// This file is automatically created and should not be edited!

#ifndef __$helper.getHelperName($intf).toUpperCase()_H__
\#define __$helper.getHelperName($intf).toUpperCase()_H__

#set($i = $intf.name())
#set($intfname = "$i$suffix")
#set($clname = "${i}Helper")

\#include "${i}Server.h"
\#include "ValueFactory${i}.h"
#if($helper.isClient($mc) || $helper.isBoth($mc))
\#include "Remote${i}Server.h"
#end
#if($helper.isServer($mc) || $helper.isBoth($mc))
\#include "Remote${i}Client.h"
#end

#if($helper.isClient($mc) || $helper.isBoth($mc))
class ${i}ClientFactory;
#end

\#include "support/EtchDefaultServerFactory.h"
\#include "support/EtchTransportHelper.h"
\#include "support/EtchRuntime.h"
\#include "transport/EtchTransportFactory.h"
\#include "util/EtchResources.h"



namespace $namespace {
  /**
   * Transport helper for ${i}. All methods are static.
   */
  class $clname : public EtchTransportHelper {
  public:
#if($helper.isServer($mc) || $helper.isBoth($mc))
    /**
     * Factory used by
     * {@link ${i}Helper#newListener(String, Resources, ${i}ServerFactory)}
     * to construct a new instance implementing {@link ${i}Server}. The new
     * instance will receive and process messages from the client session.
     */
    class ${i}ServerFactory
    {
    public:
      /**
       * Destructor
       */
      virtual ~${i}ServerFactory(){}

      /**
       * Constructs a new instance implementing ${i}Server. The new
       * instance will receive and process messages from the client session.
       *
       * @param client an instance of Remote${i}Client which may be used to
       * send messages to the client session.
       * @return a new instance implementing ${i}Server (typically
       * Impl${i}Server).
       * @throws Exception
       */
      virtual ${i}Server* new${i}Server(Remote${i}Client* client) = 0;
    };
#end
#if($helper.isClient($mc) || $helper.isBoth($mc))

    /**
     * {@link ${i}Helper#newServer(String, Resources, ${i}ClientFactory)}
     * to cinterfaceonstruct a new instance implementing {@link ${i}Client}. The new
     * instance will receive and process messages from the server session.
     */
    class ${i}ClientFactory {
    public:
      /**
       * Destructor
       */
      virtual ~${i}ClientFactory(){}

      /**
       * Constructs a new instance implementing ${i}Client. The new
       * instance will receive and process messages from the server session.
       *
       * @param server an instance of Remote${i}Server which may be used to
       * send messages to the server session.
       * @return a new instance implementing ${i}Client (typically
       * Impl${i}Client).
       * @throws Exception
       */
      virtual ${i}Client* new${i}Client(Remote${i}Server* server) = 0;
    };
#end

private:
    /**
     * Helper class for the creation of the server side factory
     */
    class Listener${i}Server : public EtchDefaultServerFactory {
      
    public:
     /**
      * Constructor
      * @param listener
      * @param implFactory implementation of the factory
      */
      Listener${i}Server(EtchTransport<EtchServerFactory>* listener, ${i}ServerFactory* implFactory);
      
      /**
       * Destructor
       */
      virtual ~Listener${i}Server();
      
      /**
       * Creates a new server stack instance
       * @param runtime the runtime the new stack instance is bound to
       * @param transport the transport layer
       * @param uri
       * @param resources
       * @return status code
       */
      status_t newServer(EtchRuntime* runtime, EtchTransportMessage* transport, const EtchString& uri, EtchResources* resources);
      
      /**
       * Creates a new valuefactury
       * @param uri
       * @param vf an existing valuefactory
       */
      status_t newValueFactory(const EtchString& uri, EtchValueFactory *&vf);
      
    private:
      ${i}ServerFactory* mFactory;
      EtchResources *mRes;
    };
 
   public:
#if($helper.isServer($mc) || $helper.isBoth($mc)) 
    static status_t newListener(EtchRuntime* runtime, EtchString uri, EtchResources* resources, ${i}ServerFactory* implFactory, EtchServerFactory*& serverFactory);
#end

#if($helper.isClient($mc) || $helper.isBoth($mc))
    static status_t newServer(EtchRuntime* runtime, EtchString uri, EtchResources* resources, ${i}ClientFactory& implFactory, Remote${i}Server*& server);
#end
  };
}

#endif /* __$helper.getHelperName($intf).toUpperCase()_H__ */
