##
## 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 = "Stub$intfname")

#ifndef __$helper.getStubName($intf, $mc).toUpperCase()_H__
\#define __$helper.getStubName($intf, $mc).toUpperCase()_H__

\#include "$inc"
#if($hasBaseClass)
\#include "Stub${i}.h"
#end
\#include "support/EtchDeliveryService.h"
#if(!$hasBaseClass)
\#include "support/EtchStubBase.h"
#end
\#include "ValueFactory${i}.h"
\#include "support/EtchStubHelper.h"
\#include "support/EtchRuntime.h"

using namespace $namespace;

#foreach( $mthd in $intf.iterator() )
#if ($mthd.isMsgDir($mc))
#if (!$mthd.isHidden())
#set( $notEmpty = true)
class Run${mthd.vname($helper)}
  : public EtchStubHelper<$i$suffix>
{
public:
  Run${mthd.vname($helper)}(EtchRuntime* runtime)
  : EtchStubHelper<$i$suffix>(runtime) {
  }
  
  ~Run${mthd.vname($helper)}() {
  }

  status_t run(EtchStubBase<$i$suffix>* _ref, EtchDeliveryService *_svc, $i$suffix *_obj, capu::SmartPointer<EtchWho> _sender, capu::SmartPointer<EtchMessage> _msg )
  {
    status_t status = ETCH_OK;
    ETCH_LOG_TRACE(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: Called ${mthd.vname($helper)} Run-Method.");
#if (!$mthd.isOneway())
    capu::SmartPointer<EtchMessage> _rmsg;
    status = _msg->createReplyMessage(_rmsg);
    if(status != ETCH_OK) {
      ETCH_LOG_TRACE(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: Coudn't create reply-message.");
      // TODO set exception
      return ETCH_ERROR;
    }

#end
    // do stub call
#set($count = 0)
#foreach($param in $mthd.iterator())
#set($count = $count + 1)
    EtchObjectPtr obj$count;
    _msg->get(ValueFactory$i::$param.vname($helper)(), &obj$count);
    $helper.getEtchTypeName($param.type(), true) val$count = capu::smartpointer_cast<$helper.getEtchTypeName($param.type(), false)>(obj$count);

#end
## TODO: ADD AUTHENTICATION CODE HERE! ############################
    $intfname::$mthd.name()AsyncResultPtr ar;
#set($sep = "")
#set($count = 0)
    ETCH_LOG_TRACE(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: Calling implementation of \"$mthd.name()\" function.");
    ar = _obj->$mthd.name()(#foreach($param in $mthd.iterator())#set($count = $count + 1)${sep}val$count#set($sep = ", ")#end);

    // create result message
#if($mthd.hasReturn())
    if(ar->hasResult()) {
    ETCH_LOG_TRACE(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: $mthd.name() - returned an Result, generating Answer Message.");
        _rmsg->put(ValueFactory$i::_mf_result(), ar->getResult());
    } else
#end
    if(ar->hasException()) {
         ETCH_LOG_DEBUG(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: $mthd.name()  - returned an Exception - notify Session.");
        _ref->sessionNotify(ar->getException());
#if ($mthd.isOneway())
        EtchMessagePtr _rmsg;
        _msg->createReplyMessage( _msg->getValueFactory()->get_mt__exception(), _rmsg );
#end
        _rmsg->put( ValueFactory$i::_mf_result(), ar->getException() );
#if ($mthd.isOneway())
        // transport result message
        ETCH_LOG_TRACE(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: $mthd.name() - (One-Way) Transport Message back! Because an Exception occurred!.");
        status = _svc->transportMessage( _sender, _rmsg);
#end
    }

#if (!$mthd.isOneway())
    // transport result message
    ETCH_LOG_TRACE(mRuntime->getLogger(), mRuntime->getLogger().getDeliveryServiceContext(), "Stub$i$suffix ${namespace}: $mthd.name() - Transport answer-message back!.");
    status = _svc->transportMessage( _sender, _rmsg);
#end
    return status;
  }
};
#end
#end
#end

namespace $namespace {
#if ($hasBaseClass)

  /**
   * Message to call translator for $i$suffix.
   */
  class Stub$i$suffix : public Stub$i<$i$suffix>
#set( $T = "$i$suffix" )
#else
  /**
   * Message to call translator for $i$suffix.
   * @param <T> $i$suffix or a subclass thereof.
   */
  template<typename T>
  class Stub$i$suffix : public EtchStubBase<T>
#set( $T = "T" )
#end
  {
    /**
    * Stub for $i$suffix.
    * @param svc the delivery service.
    * @param obj the implementation of $i$suffix responsive to requests.
    * @param free thread pool used to run AsyncMode.FREE methods.
    * @param queued thread pool used to run AsyncMode.QUEUED methods.
    */
  public:
#if(!$hasBaseClass)
    Stub$i$suffix( EtchDeliveryService *svc, $T *obj, EtchQueuedPool* queued, EtchFreePool* free)
      : EtchStubBase<T>(svc, obj, queued, free)
#else
    Stub$i$suffix( EtchDeliveryService *svc, $T *obj, EtchQueuedPool* queued, EtchFreePool* free)
      : Stub$i<$i$suffix>(svc, obj, queued, free)
#end
    {
    }
    virtual ~Stub$i$suffix() {}
    

##if($notEmpty)
   
  private:
    friend class ValueFactory${i};
    
    /**
     * Static Initialization-Helper
     */
    static status_t Init(EtchRuntime* runtime)
    {
#foreach( $mthd in $intf.iterator() )
#if ($mthd.isMsgDir($mc))
#if (!$mthd.isHidden())
      ValueFactory$i::${mthd.vname( $helper )}->setStubHelper(new Run${mthd.vname($helper)}(runtime));
#end
#end
#if( $n.isMixin() )
#set( $m = $n.getModule() )
#set( $z = $m.iterator().next() )
      ${m.name()}::Stub${z.name()}${suffix}::Init(runtime);
#end
#end
      return ETCH_OK;
    }
##end
  };
}

#endif /* __$helper.getStubName($intf, $mc).toUpperCase()_H__ */
