##
## 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!
#set($i = $intf.name())
#set($intfname = "$i$suffix")
#set($clname = "${i}Helper")

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

\#include "support/EtchRuntime.h"
\#include "support/EtchStackClient.h"
\#include "support/EtchStackServer.h"
\#include "support/EtchPool.h"
\#include "transport/EtchPlainMailboxManager.h"
\#include "transport/EtchDefaultDeliveryService.h"

using namespace $namespace;

#if($helper.isServer($mc) || $helper.isBoth($mc))
$clname::Listener${i}Server::Listener${i}Server(EtchTransport<EtchServerFactory>* listener, ${i}ServerFactory* implFactory)
  : EtchDefaultServerFactory(listener, NULL), mFactory(implFactory)
{
  
}

$clname::Listener${i}Server::~Listener${i}Server()
{
  
}

status_t $clname::Listener${i}Server::newServer(EtchRuntime* runtime, EtchTransportMessage* transport, const EtchString& uri, EtchResources* resources)
{
  //get stack instance
  EtchStackServer* stack = NULL;
  resources->get(EtchStack::STACK(), (EtchObject*&)stack );

  //get value factory
  EtchObject* obj;
  resources->get( EtchTransport<EtchValueFactory*>::VALUE_FACTORY(), obj );
  EtchValueFactory* vf = (EtchValueFactory*) obj;
  
  //create stack layers
  EtchMailboxManager* mbm = new EtchPlainMailboxManager(runtime, transport, uri, resources);
  stack->setMailboxManager(mbm);
  EtchDeliveryService* dvs = new EtchDefaultDeliveryService(runtime, mbm, uri);
  stack->setDeliveryService(dvs);
  Remote${i}Client* client = new Remote${i}Client(runtime, dvs, vf, stack);
  stack->setRemote(client);
  ${i}Server* server = mFactory->new${i}Server(client);
  
  //get thread pools
  EtchObject* tmpObject;
  resources->get( QUEUED_POOL(), tmpObject );
  EtchQueuedPool* qp = (EtchQueuedPool*) tmpObject;
  resources->get( FREE_POOL(), tmpObject );
  EtchFreePool* fp = (EtchFreePool*) tmpObject;
  
  //create stub
  Stub${i}Server* tmp${i}Server = new Stub${i}Server(dvs, server, qp, fp);
  stack->setStub(tmp${i}Server);
  
  //start remote client
  client->start();
  return ETCH_OK;
}

status_t $clname::Listener${i}Server::newValueFactory(const EtchString& uri, EtchValueFactory *&vf)
{
  vf = new ValueFactory${i}(uri);
  return ETCH_OK;
}


/**
 * Constructs a new server session listener per specifications in uri and
 * resources. This listener will accept requests from clients for new server
 * sessions.
 *
 * @param uri contains specifications for the server session listener and
 * for the server session transport stack.
 *
 * @param resources additional resources to aid in constructing new server
 * sessions.
 *
 * @param implFactory factory used to construct a new instance implementing
 * ${i}Server. The new instance will receive and process messages from
 * the client session.
 *
 * @return a server session listener.
 *
 * @throws Exception
 */
status_t $clname::newListener(EtchRuntime* runtime, EtchString uri, EtchResources* resources, ${i}ServerFactory* implFactory, EtchServerFactory*& serverFactory)
{
  status_t status = ETCH_OK;

  //static initialization of value factory
  ValueFactory${i}::InitValueFactory(runtime);

  //init resources
  EtchResources *res;
  status = EtchTransportHelper::InitResources(runtime, resources, res);
  if (status != ETCH_OK) {
    return status;
  }
  
  //get listener
  EtchTransport<EtchServerFactory>* listener;
  EtchTransportFactory::getListener(runtime, uri, res, listener);
  
  //create server
  serverFactory = new $clname::Listener${i}Server(listener, implFactory);
  return status;
}
#end

#if($helper.isClient($mc) || $helper.isBoth($mc))
  /**
   * Constructs a new client session per specifications in uri and resources.
   *
   * @param uri contains specifications for the client session transport
   * stack.
   *
   * @param resources additional resources to aid in constructing new client
   * sessions.
   *
   * @param implFactory factory used to construct a new instance implementing
   * ${i}Client. The new instance will receive and process messages from
   * the server session.
   *
   * @return an instance of Remote${i}Server initialized by uri and
   * resources which may be used to send messages to the server session.
   *
   * @throws Exception
   */
  status_t $clname::newServer(EtchRuntime* runtime, EtchString uri, EtchResources* resources, ${i}ClientFactory& implFactory, Remote${i}Server*& server)
  {
    status_t status = ETCH_OK;

    EtchStackClient* stack = new EtchStackClient(runtime);

    //static initialization of value factory
    ValueFactory${i}::InitValueFactory(runtime);

    //init resources
    EtchResources* res;
    status = InitResources(runtime, resources, res);
    if (status != ETCH_OK) {
      return status;
    }
    
    EtchObject* tmp = NULL;
    res->put(EtchStack::STACK(),stack, tmp);
    stack->mStaticResources = res;
    
    //create valuefactory instance
    ValueFactory${i}* vf = new ValueFactory${i}(uri);
    stack->setValueFactory(vf);
    EtchObject* vfobj = (EtchObject*) vf;
    EtchObject* resobj = NULL;
    res->put(EtchTransport<ValueFactory${i}>::VALUE_FACTORY(), vfobj, resobj);
    if(resobj != NULL) delete resobj;

    //init stack layers
    EtchTransportMessage* m;
    EtchTransportFactory::getTransport(runtime, uri, res, m);
    EtchMailboxManager* mbm = new EtchPlainMailboxManager(runtime, m, uri, res);
    stack->setMailboxManager(mbm);
    EtchDeliveryService* dvs = new EtchDefaultDeliveryService(runtime, mbm, uri);
    stack->setDeliveryService(dvs);
    Remote${i}Server* _server = new Remote${i}Server(runtime, dvs, vf, stack);
    ${i}Client* client = implFactory.new${i}Client( server );
    
    //get pools
    EtchObject* tmpObject;
    res->get(QUEUED_POOL(), tmpObject);
    EtchQueuedPool* qp = (EtchQueuedPool*) tmpObject;
    res->get(FREE_POOL(), tmpObject);
    EtchFreePool* fp = (EtchFreePool*) tmpObject;
    
    //init stub
    Stub${i}Client* tmpStub${i}Client = new Stub${i}Client(dvs, client, qp, fp);
    stack->setStub(tmpStub${i}Client);
    
    //return server
    server = _server;
    return status;
  }
#end
