##
## 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;
  status = EtchTransportFactory::getListener(runtime, uri, res, listener);
  if (status != ETCH_OK) {
    ETCH_LOG_ERROR(runtime->getLogger(), runtime->getLogger().getRuntimeContext(), "Listener could not be created by the transport factory for the given URI.");
    return status;
  }
  
  //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
