CorbaPort.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: euc-jp -*-
00003 
00004 ##
00005 #  \file  CorbaPort.py
00006 #  \brief CorbaPort class
00007 #  \date  $Date: 2007/09/26 $
00008 #  \author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara
00009 # 
00010 #  Copyright (C) 2006-2008
00011 #      Noriaki Ando
00012 #      Task-intelligence Research Group,
00013 #      Intelligent Systems Research Institute,
00014 #      National Institute of
00015 #          Advanced Industrial Science and Technology (AIST), Japan
00016 #      All rights reserved.
00017 
00018 from omniORB import CORBA
00019 from omniORB import any
00020 import traceback
00021 import sys
00022 
00023 import OpenRTM_aist
00024 import RTC
00025 
00026 
00027 
00028 ##
00029 # @if jp
00030 # @class CorbaPort
00031 # @brief RT コンポーネント CORBA provider/consumer 用 Port
00032 #
00033 # CorbaPort は RT コンポーネントにおいて、ユーザ定義の CORBA オブジェ
00034 # クトサービスおよびコンシューマを提供する Port 実装である。
00035 #
00036 # RT コンポーネントは、Port を介してユーザが定義した CORBA サービス
00037 # を提供することができ、これを RT Service (Provider) と呼ぶ。また、
00038 # 他の RT コンポーネントのサービスを利用するための CORBA オブジェク
00039 # トのプレースホルダを提供することができ、これを RT Service
00040 # Consumer と呼ぶ。
00041 # CorbaPort は任意の数の Provider および Consumer を管理することがで
00042 # き、Port 同士を接続する際に対応する Provider と Consumer を適切に
00043 # 関連付けることができる。
00044 # CorbaPort は通常以下のように利用される。
00045 #
00046 # <pre>
00047 # RTC::CorbaPort m_port0; // Port の宣言
00048 #
00049 # MyService_impl m_mysvc0; // この Port が提供する Serivce Provider
00050 # RTC::CorbaConsumer<YourService> m_cons0; // この Port の Consumer
00051 #
00052 # // Service Provider を Port に登録
00053 # m_port0.registerProvider("MyService0", "Generic", m_mysvc0);
00054 # // Service Consumer を Port に登録
00055 # m_port0.registerConsumer("YourService0", "Generic", m_cons0 );
00056 #
00057 # // connect が行われた後
00058 #
00059 # m_cons0->your_service_function(); // YourService の関数をコール
00060 #
00061 # // connect された 別のコンポーネントにおいて
00062 # m_cons1->my_service_function(); // MyService の関数をコール
00063 # </pre>
00064 #
00065 # このように、提供したい Service Provider を registerProvider() で登
00066 # 録することにより、他のコンポーネントから利用可能にし、他方、利用し
00067 # たい Service Consumer を registerConsumer() で登録することにより他
00068 # のコンポーネントの Service をコンポーネント内で利用可能にすること
00069 # ができる。
00070 #
00071 # PortInterfaceProfile は Port に所属するプロバイダもしくはコンシュー
00072 # マインターフェースについての情報を記述するためのプロファイルである。
00073 # 接続を行うツール等は、これらの情報に基づき ConnectorProfile を適切
00074 # に生成し、接続を構成する Port のうち任意の一つに対して引数に
00075 # ConnectorProfile を与えて Port::connect() を呼び出す必要がある。
00076 #
00077 # なお、PortInterfaceProfile のインスタンス名 "#" は特殊なインスタン
00078 # スを表す。
00079 #
00080 # PROVIDEDすなわちプロバイダのインスタンス名が "#" の場合は、接続開
00081 # 始時点ではインスタンスが存在せず、コンシューマの要求に応じて動的に
00082 # インスタンスを生成するタイプのプロバイダであることを表す。したがっ
00083 # て、接続開始時点ではインスタンス名は存在しないが、接続シーケンス中
00084 # のインターフェースを公開するプロセスにおいて、プロバイダは生成した
00085 # インスタンスに対応した記述子を ConnectorProfile に適正に設定するも
00086 # のとする。(未実装)
00087 #
00088 # REQUIREDすなわちコンシューマのインスタンス名が "#" の場合は、一つ
00089 # のコンシューマが複数のプロバイダと接続可能なタイプのコンシューマで
00090 # あることを示す。(未実装)
00091 #
00092 # 以下は、Port間のインターフェースを接続するために ConnectorProfile に
00093 # マッピングを記述するためのルールを示す。
00094 #
00095 # Portに付属するインターフェースの指定子のフォーマットを以下のように
00096 # 定める。インターフェースに関するプロパティが以下の場合
00097 #
00098 # - RTCインスタンス名:              rtc_iname
00099 # - ポート名:                       port_name
00100 # - インターフェース極性:           if_polarity
00101 # - インターフェース型名:           if_tname
00102 # - インターフェースインスタンス名: if_iname
00103 # 
00104 # インターフェースの指定子を以下の文字列名称で指定するものとする。
00105 #
00106 # <rtc_iname>.port.<port_name>.<if_polarity>.<if_tname>.<if_iname>
00107 #
00108 # PROVIDED(提供)型すなわちプロバイダのインタフェースのプロパティが以
00109 # 下の場合、
00110 #
00111 # - rtc_iname   = MyComp0
00112 # - port_name   = myservice
00113 # - if_polarity = provided
00114 # - if_tname    = echo_interface
00115 # - if_iname    = echo_interface2
00116 #
00117 # インターフェース指定子は
00118 #
00119 # MyComp0.port.myservice.provided.echo_interface.echo_interface2
00120 #
00121 # のように記述される。また、同様にREQUIRED(要求)型すなわちコンシュー
00122 # マのインターフェースのプロパティが以下の場合、
00123 #
00124 # - rtc_iname   = YourComp0
00125 # - port_name   = yourservice
00126 # - if_polarity = required
00127 # - if_tname    = hoge_interface
00128 # - if_iname    = hoge_interface1
00129 #
00130 # インターフェース指定子は、
00131 # 
00132 # YourComp0.port.myservice.required.hoge_interface.hoge_inteface1
00133 #
00134 # のように記述することができる。
00135 # 
00136 # なお、ここで動的生成インターフェースのインスタンスのための特殊なタ
00137 # イプのインスタンス名記述子
00138 #
00139 # - <type_name>*: 動的生成型インスタンス名記述子
00140 # - <type_name>+: インクリメンタル生成型インスタンス名記述子
00141 #
00142 # を定義する。動的生成インターフェースとは、接続時にインスタンスが生
00143 # 成されるタイプのインターフェースである。(未実装)
00144 #
00145 # コンシューマが要求するプロバイダインターフェース記述子に動的生成型
00146 # インスタンス名記述子 "<type_name>#" が指定された場合、プロバイダは
00147 # インスタンスを1つ新規に生成する。"<type_name>#" の記述子によりプロバ
00148 # イダを要求する n 個のコンシューマが存在する場合、これらからの要求
00149 # (オペレーションコール)を1 つのプロバイダにより処理する関係を構築す
00150 # る(下図)。
00151 #
00152 # <pre>
00153 # consumer0 ]---<
00154 # consumer1 ]---<  O----[ provider0
00155 # consumer2 ]---<
00156 # </pre>
00157 #  
00158 # これに対し、コンシューマが要求するプロバイダインターフェース記述子
00159 # にインクリメンタル生成型インスタンス名記述子 "<type_name>+" が指定
00160 # された場合、記述子 "<type_name>+" の数だけプロバイダのインスタン
00161 # スが動的に生成される。すなわち、"<type_name>+" の記述子によりプロバ
00162 # イダを要求する n 個のコンシューマが存在する場合、n 個のプロバイダ
00163 # がそれぞれの要求を処理する以下のような関係が構築される。
00164 #
00165 # <pre>
00166 # consumer0 ]---<  O----[ provider0
00167 # consumer1 ]---<  O----[ provider1
00168 # consumer2 ]---<  O----[ provider2
00169 # </pre>
00170 #
00171 #
00172 # 接続に際して、ツール等から ConnectorProfile::properties に適切なイ
00173 # ンターフェースマッピング指定を記述することで、相互のプロバイダ/コ
00174 # ンシューマインターフェースを自由に接続することができる。ただし、接
00175 # 続に関わる RTC の中に、異なるインスタンスでありながら、同一のインス
00176 # タンス名が存在する場合、インターフェース記述子の一意性が保証できな
00177 # いので、この方法による接続性は保証されない。
00178 #
00179 # ここでインターフェース記述子を簡単のために <if_desc0>,
00180 # <if_desc1>, ...  とする。また、ConnectorProfile::properties の
00181 # NVListの key と value を key: value のように記述するものとする。
00182 #
00183 # いま、2つのコンポーネントのサービスポートを接続する場合を考える。
00184 # それぞれのコンポーネントのサービスポートが以下の場合、
00185 #
00186 # - rtc_iname: MyComp0        <br>
00187 #   port_name: mycomp_service <br>
00188 #   interfaces:
00189 #   - if_polarity: provided   <br>
00190 #     if_iname: echo0         <br>
00191 #     if_tname: Echo
00192 #   - if_polarity: required   <br>
00193 #     if_iname: add0          <br>
00194 #     if_tname: add
00195 #
00196 # - rtc_iname: YourComp0        <br>
00197 #   port_name: yourcomp_service <br>
00198 #   interfaces:
00199 #   - if_polarity: required     <br>
00200 #     if_iname: echo9           <br>
00201 #     if_tname: Echo
00202 #   - if_polarity: provided     <br>
00203 #     if_iname: add9            <br>
00204 #     if_tname: add
00205 #
00206 # <pre>
00207 #      MyComp0                                 YourComp0
00208 #     _______ mycomp_service   yourcomp_service ______
00209 #            |                                 |
00210 #          |~~~|---O echo0         echo9 >---|~~~|
00211 #          |   |---< add0          add9  O---|   |
00212 #           ~T~                               ~T~
00213 #            |                                 |
00214 # </pre>
00215 #
00216 # MyComp0 の echo0 (プロバイダ) と YourComp0 の echo9 (コンシューマ)、
00217 # MyComp0 の add0 (コンシューマ) と YourComp0 の add9 (プロバイダ)
00218 # をそれぞれ対にして接続させるものと仮定する。この場合、
00219 # ConnectorProfile は以下のように設定する。
00220 # 
00221 # <pre>
00222 # ConnectorProfile:
00223 #   name: 任意のコネクタ名
00224 #   connector_id: 空文字
00225 #   ports[]: mycomp_service の参照, yourcomp_service の参照
00226 #   properties:
00227 #     <add0>: <add9>
00228 #     <echo9>: <echo0>
00229 # </pre>
00230 #
00231 # ただし、それぞれ
00232 # 
00233 # <pre>
00234 # <add0> は MyComp0.port.mycomp_service.required.add.add0
00235 # <add9> は YourComp0.port.yourcomp_service.provided.add.add9
00236 # <echo0> は MyComp0.port.mycomp_service.provided.echo.echo0
00237 # <echo9> は YourComp0.port.yourcomp_service.required.echo.echo9
00238 # </pre>
00239 #
00240 # である。接続プロセスにおいて、各ポートのプロバイダおよびコンシュー
00241 # マは、それぞれ以下の作業を、CorbaPort::publishInterfaces(),
00242 # CorbaPort::subscribeInterfaces() 仮想関数において行う。
00243 #
00244 # プロバイダは、publishInterfaces() 関数において、自分のインターフェー
00245 # ス記述子をキーとし、値にIORの文字列表記したものを
00246 # ConnectorProfile::properties に設定する。前提として、このインター
00247 # フェース記述子は今行おうとしているコネクタにおいては一意であるため、
00248 # 同じキーは1つしか存在してはいけない。
00249 #
00250 # [この部分の記述は未実装の機能] なお、動的生成インターフェースにつ
00251 # いては、以下の手続きに従い処理することとなる。publishInterface()
00252 # 関数において、動的生成インスタンス名記述子 "<type_name>*" または、
00253 # インクリメンタル生成型インスタンス名記述子 "<type_name>+" が存在す
00254 # るかどうかを走査する。動的生成インスタンス名記述子 "<type_name>*"
00255 # が存在する場合、プロバイダのインスタンスを1つ生成し、そのインター
00256 # フェース指定子を key に、IOR文字列を value に設定するとともに、動
00257 # 的生成インスタンス名記述子 "<type_name>*" を value に含むすべての
00258 # value 上のインターフェース指定子を、ここで生成したインターフェース
00259 # 指定子に置き換える。
00260 # 
00261 # インクリメンタル生成型インスタンス名記述子"<type_name>+" が存在す
00262 # る場合、インスタンス名記述子の数だけプロバイダのインスタンスを生成
00263 # し、それぞれのインターフェース指定子をkey に、IOR文字列を value に
00264 # 設定するとともに、インクリメンタル生成型インスタンス名記述子
00265 # "<type_name>+" を value 含むすべての value 上のインターフェース指
00266 # 定子に対して順に、ここで生成したそれぞれのインターフェース指定子に
00267 # 置き換える。
00268 #
00269 # プロバイダは subscribeInterfaces() では特に操作は行わない。
00270 #
00271 # コンシューマは、 publishInterfaces() においては特に操作を行わない。
00272 #
00273 # 一方、 subscribeInterfaces() では、自分の記述子を key とする
00274 # key-value ペア が存在するかどうか調べ、もし存在すれば、その value
00275 # に設定されたプロバイダのインターフェース指定子で指定される参照を、
00276 # さらに ConnectorProfile::properties から探し、それをコンシューマの
00277 # 接続先として設定する。なお、意図的にコンシューマにプロバイダの参照
00278 # を設定しない場合は、予約文字列 "nil" または "null" を設定するもの
00279 # とする。
00280 #
00281 # コンシューマは、もし自分の記述子が存在しない場合、またはプロバイダ
00282 # の参照が Connector::properties に存在しない場合、コンシューマは、
00283 # 自分のインスタンス名および型名と同一のプロバイダを探し、その参照を
00284 # 自分自身に設定する。これは、OpenRTM-aist-0.4 との互換性を保持する
00285 # ためのルールであり、1.0以降では推奨されない。
00286 #
00287 # プロバイダ対コンシューマの対応は一対一である必要はなく、プロバイダ
00288 # 1 に対して、コンシューマ n、またはコンシューマ 1 に対してプロバイ
00289 # ダ n のケースも許される。プロバイダ 1 に対して、コンシューマ n の
00290 # ケースでは、あるプロバイダの指定子が、複数のコンシューマに対して、
00291 # 上記の方法で指定されることにより、実現される。一方、コンシューマ
00292 # 1 に対してプロバイダ n のケースでは、コンシューマ指定子の key に対
00293 # して、複数のプロバイダの指定子がカンマ区切りで列挙される形式となる
00294 # ものとする。
00295 #
00296 # なお、インターフェースの対応関係の厳密さを指定するオプションとして、
00297 # 以下のオプションを指定することができる。
00298 #
00299 # port.connection.strictness: strict, best_effort 
00300 #
00301 # strict: すべてのコンシューマに指定した参照が存在し、かつナローイン
00302 #         グにも成功しコンシューマに適切にセットできた場合にのみ Port
00303 #         間の接続を確立する。
00304 #
00305 # best_effort: ナローイング等に失敗した場合でも、エラーを返すことな
00306 #         く Port 間の接続を確立する。
00307 #
00308 # @since 0.4.0
00309 #
00310 # @else
00311 # @class CorbaPort
00312 # @brief RT Conponent CORBA service/consumer Port
00313 #
00314 # CorbaPort is an implementation of the Port of RT-Component's that provides
00315 # user-defined CORBA Object Service and Consumer.
00316 # <p>
00317 # RT-Component can provide user-defined CORBA serivces, which is called
00318 # RT-Serivce (Provider), through the Ports.
00319 # RT-Component can also provide place-holder, which is called RT-Serivce
00320 # Consumer, to use other RT-Component's service.
00321 # <p>
00322 # The CorbaPort can manage any number of Providers and Consumers, can
00323 # associate Consumers with correspondent Providers when establishing
00324 # connection among Ports.
00325 # <p>
00326 # Usually, CorbaPort is used like the following.
00327 #
00328 # <pre>
00329 # RTC::CorbaPort m_port0; // declaration of Port
00330 #
00331 # MyService_impl m_mysvc0; // Serivce Provider that is provided by the Port
00332 # RTC::CorbaConsumer<YourService> m_cons0; // Consumer of the Port
00333 #
00334 # // register Service Provider to the Port
00335 # m_port0.registerProvider("MyService0", "Generic", m_mysvc0);
00336 # // register Service Consumer to the Port
00337 # m_port0.registerConsumer("YourService0", "Generic", m_cons0 );
00338 #
00339 # // after connect established
00340 #
00341 # m_cons0->your_service_function(); // call a YourService's function
00342 #
00343 # // in another component that is connected with the Port
00344 # m_cons1->my_service_function(); // call a MyService's function
00345 # </pre>
00346 #
00347 # Registering Service Provider by registerProvider(), it can be
00348 # used from other RT-Components.  Registering Service Consumer by
00349 # registerConsumer(), other RT-Component's services can be used
00350 # through the consumer object.
00351 #
00352 # PortInterfaceProfile is a one of the profile information to store
00353 # Provider interface and Consumer interface information. Tools or
00354 # other RTCs should call one of the Port::connect() with an
00355 # appropriate ConnectorProfile.
00356 #
00357 # In addition, the instance name "*" declares a special type of instance.
00358 #
00359 # When the name of the PROVIDED type interface that is the provider
00360 # interface is "*", Provider interface's instance does not exist at
00361 # the beginning of connection sequence.  The instances will be
00362 # created dynamically according to the consumer interface
00363 # requirement at the connection sequence.  Although the instance
00364 # name does not exist at the beginning of connection sequence, the
00365 # created providers shall publish its references to the
00366 # ConnectorProfile with interface descriptor adequately in the
00367 # interface publisher phase of the connection sequence.
00368 #
00369 # If REQUIRED interface name that is Consumer interface name is
00370 # "*", it shows that one Consumer interface is able to connect with
00371 # multiple Provider interfaces. (This feature is not implemented.)
00372 # 
00373 # The following describes the rules that specify interface
00374 # connection between ports.
00375 #
00376 # The descriptor format of interfaces associated with Ports is
00377 # declared as follows. Now some of interface properties are assumed
00378 # as the followings.
00379 #
00380 # - RTC instance name:              rtc_iname
00381 # - Port name:                      port_name
00382 # - Interface polarity:             if_polarity
00383 # - Interface type name:            if_tname
00384 # - INterface instance name:        if_iname
00385 #
00386 # The interface descriptors shall be declared as follows.
00387 #
00388 # <rtc_iname>.port.<port_name>.<if_polarity>.<if_tname>.<if_iname>
00389 #
00390 # When PROVIDED that is Provider interface properties are the followings,
00391 #
00392 # - rtc_iname   = MyComp0
00393 # - port_name   = myservice
00394 # - if_polarity = provided
00395 # - if_tname    = echo_interface
00396 # - if_iname    = echo_interface2
00397 # the interface descriptor is here.
00398 #
00399 # MyComp0.port.myservice.provided.echo_interface.echo_interface2
00400 #
00401 # And, when REQUIRED that is Consumer interfaces properties are the
00402 # followings,
00403 #
00404 # - rtc_iname   = YourComp0
00405 # - port_name   = yourservice
00406 # - if_polarity = required
00407 # - if_tname    = hoge_interface
00408 # - if_iname    = hoge_interface1
00409 #
00410 # interface descriptor is as follows. 
00411 #
00412 # YourComp0.port.myservice.required.hoge_interface.hoge_inteface1
00413 #
00414 # Specific instance name descriptors that are dynamically generated
00415 # at the connection time are defined here.
00416 #
00417 # - <type_name>*: "Dynamically generated" instance descriptor.
00418 # - <type_name>+: "Incrementally generated" instance descriptor.
00419 #
00420 # When the "Dynamically generated" instance descriptor:
00421 # "<type_name>*" is specified as interface descriptor that is
00422 # required by consumers, the provider will generate a instance. If
00423 # n consumers who demand a provider by the "<type_name>" descriptor
00424 # exist, the following relation which processes the call from these
00425 # consumers by one provider will be established.
00426 #
00427 # <pre>
00428 # consumer0 ]---<
00429 # consumer1 ]---<  O----[ provider0
00430 # consumer2 ]---<
00431 # </pre>
00432 #  
00433 # On the other hand, when incremental generated type instance name
00434 # descriptor "<type_name>+" is specified as the provider interface
00435 # descriptor whom consumers demand, provider's instances are
00436 # dynamically generated for the number of the descriptors
00437 # "<type_name>+". When n consumers who demand a provider by the
00438 # descriptor "<type_name>+" exist the following relations in which
00439 # n providers process each call from the consumers will be
00440 # established.
00441 #
00442 # <pre>
00443 # consumer0 ]---<  O----[ provider0
00444 # consumer1 ]---<  O----[ provider1
00445 # consumer2 ]---<  O----[ provider2
00446 # </pre>
00447 #
00448 #
00449 # Describing the appropriate interface mapping specification in the
00450 # ConnectorProfile::properties, selective connections between
00451 # providers/consumers interface can be established at the time of
00452 # connection. However, when different RTC instances of the same
00453 # instance name exist in a connection, since an interface
00454 # descriptor uniqueness cannot be guaranteed, this connection
00455 # mapping rules cannot be used.
00456 #
00457 # Here, assume that an interface descriptor is given as <if_desc0>,
00458 # <if_desc1>, .... And assume that the key and the value of NVList
00459 # in ConnectorProfile::properties are given as "key: value".
00460 #
00461 # Now the case where the service ports of two components are
00462 # connected is considered. When the service port of each component
00463 # is the following,
00464 # 
00465 # - rtc_iname: MyComp0          <br>
00466 #   port_name: mycomp_service   <br>
00467 #   interfaces:
00468 #   - if_polarity: provided     <br>
00469 #     if_iname: echo0           <br>
00470 #     if_tname: Echo
00471 #   - if_polarity: required     <br>
00472 #     if_iname: add0            <br>
00473 #     if_tname: add
00474 #
00475 # - rtc_iname: YourComp0        <br>
00476 #   port_name: yourcomp_service <br>
00477 #   interfaces:
00478 #   - if_polarity: required     <br>
00479 #     if_iname: echo9           <br>
00480 #     if_tname: Echo
00481 #   - if_polarity: provided     <br>
00482 #     if_iname: add9            <br>
00483 #     if_tname: add
00484 #
00485 #
00486 # <pre>
00487 #      MyComp0                                 YourComp0
00488 #     _______ mycomp_service   yourcomp_service ______
00489 #            |                                 |
00490 #          |~~~|---O echo0         echo9 >---|~~~|
00491 #          |   |---< add0          add9  O---|   |
00492 #           ~T~                               ~T~
00493 #            |                                 |
00494 # </pre>
00495 # 
00496 #
00497 #
00498 # Assume that connection between echo0 (provider) of MyComp0
00499 # component and echo9 (consumer) of YourComp0 component, and add0
00500 # (consumer) of MyComp0 and add0 (provider) of YourComp0 is
00501 # established.  In this case, ConnectorProfile is set up as
00502 # follows.
00503 # 
00504 # <pre>
00505 # ConnectorProfile:
00506 #   name: any connector name
00507 #   connector_id: empty string
00508 #   ports[]: mycomp_service's reference, yourcomp_service's reference
00509 #   properties:
00510 #     <add0>: <add9>
00511 #     <echo9>: <echo0>
00512 # </pre>
00513 #
00514 # Please note that <add0>, <add9>, <echo0> and <echo9> are the following.
00515 # 
00516 # <pre>
00517 # <add0> is MyComp0.port.mycomp_service.required.add.add0
00518 # <add9> is YourComp0.port.yourcomp_service.provided.add.add9
00519 # <echo0> is MyComp0.port.mycomp_service.provided.echo.echo0
00520 # <echo9> is YourComp0.port.yourcomp_service.required.echo.echo9
00521 # </pre>
00522 #
00523 # In the connection process, the provider and the consumer of each
00524 # port carries out the following process respectively in the
00525 # virtual functions such as CorbaPort::publishInterfaces() and
00526 # CorbaPort::subscribeInerfaces().
00527 # 
00528 # A provider sets its IOR string as a value and its interface
00529 # descriptor as a key in the ConnectorProfile::properties in a
00530 # publishInterfaces() function. Since this interface descriptor's
00531 # uniqueness is guaranteed in the current connector, the key of
00532 # NameValue in the ConnectorProfile::properties is unique.
00533 #
00534 #
00535 # [This functionalities are not implemented] The dynamically
00536 # generated provider is processed according to the following
00537 # procedure. The publishInterface() function scans dynamic instance
00538 # descriptors such as "<type_name>*" and "<type_name>+" in the
00539 # ConnectorProfile::properties. When the dynamic generation
00540 # instance descriptor "<tupe_name>*" exists, one instance of
00541 # provider is generated, and its descriptor and its IOR string are
00542 # set to ConnectorProfile::properties as the key and the value
00543 # respectively. Simultaneously, in the
00544 # ConnectorProfile::properties, all the instance descriptor with
00545 # the dynamic generation instance name "<type_name>*" will be
00546 # replaced with newly generated instance descriptor.
00547 #
00548 # When the incremental dynamic generation instance descriptor
00549 # exists, providers are generated for the number of the
00550 # descriptors, and its descriptor and its IOR string are set to
00551 # ConnectorProfile::properties as the key and the value
00552 # respectively. Simultaneously, in the
00553 # ConnectorProfile::properties, all the instance descriptor with
00554 # the dynamic generation instance name "<type_name>+" will be
00555 # replaced with newly generated instance descriptor.
00556 #
00557 # The providers do not perform particular operation in
00558 # subscribeInterfaces() function.
00559 #
00560 #
00561 # The consumers do not perform particular operation in
00562 # publisherInterfaces() function.
00563 #
00564 # On the other hand, a consumer searches a key-value pair with the
00565 # key of consumer interface descriptor, and if the pair exists, it
00566 # obtains provider's descriptor from the value. The consumer
00567 # searches again a key-value pair with the key of provider
00568 # interface descriptor, and it obtains provider's reference and the
00569 # reference is set as the consumer's service object. In addition,
00570 # reserved string "nil" or "null" are used not to set specific
00571 # provider.
00572 #
00573 # If consumer's interface descriptors does not exists in the
00574 # ConnectorProfile::properties, the consumer searches a provider
00575 # with same type name and instance name, and its reference is set
00576 # to the consumer. This rule is for only backward compatibility,
00577 # and it is not recommended from version 1.0.
00578 #
00579 # The correspondence of a provider versus a consumer does not need
00580 # to be one to one, and the case of one provider to n-consumers and
00581 # the case of m-providers to one consumer are allowed. The one
00582 # provider to n-consumers case can be realized by the above
00583 # mentioned methods. The one consumer to m-provider case can be
00584 # specified to set the consumer descriptor and comma-separated
00585 # provider descriptors into the key and the value respectively.
00586 #
00587 # The following option is available to specify the strictness of
00588 # interfaces connection.
00589 #
00590 # port.connection.strictness: strict, best_effort
00591 #
00592 # strict: The connection is established, if only all the specified
00593 #         consumers are set appropriate references and narrowed
00594 #         successfully.  
00595 #
00596 # best_effort: The connection is established without any errors,
00597 #         even if appropriate reference does not exist or reference
00598 #         narrowing fails.
00599 #
00600 # @since 0.4.0
00601 #
00602 # @endif
00603 #
00604 class CorbaPort(OpenRTM_aist.PortBase):
00605   """
00606   """
00607 
00608   ##
00609   # @if jp
00610   # @brief コンストラクタ
00611   #
00612   # @param self
00613   # @param name Port の名前
00614   #
00615   # @else
00616   #
00617   # @brief Constructor
00618   #
00619   # @param name The name of Port 
00620   #
00621   # @endif
00622   def __init__(self, name):
00623     OpenRTM_aist.PortBase.__init__(self, name)
00624     self.addProperty("port.port_type", "CorbaPort")
00625     self._properties = OpenRTM_aist.Properties()
00626     self._providers = []
00627     self._consumers = []
00628     return
00629 
00630 
00631   def __del__(self, PortBase=OpenRTM_aist.PortBase):
00632     PortBase.__del__(self)
00633 
00634 
00635   ##
00636   # @if jp
00637   # @brief プロパティの初期化
00638   #
00639   # OutPortのプロパティを初期化する。このポートへの接続数を指定する
00640   # プロパティ "connection_limit" が含まれ、適切な数値が設定されてい
00641   # る場合、最大接続数としてその数値が設定される。プロパティが設定さ
00642   # れていない場合、もしくは適切な値が設定されていない場合には、最大
00643   # 接続数は無制限となる。
00644   #
00645   # @param prop CorbaPort のプロパティ
00646   #
00647   # @else
00648   #
00649   # @brief Initializing properties
00650   #
00651   # This operation initializes outport's properties. If a property
00652   # "connection_limit" is set and appropriate value is set to this
00653   # property value, the number of maximum connection is set as this
00654   # value. If the property does not exist or invalid value is set
00655   # to this property, the maximum number of connection will be set
00656   # unlimited.
00657   #
00658   # @param prop properties of the CorbaPort
00659   #
00660   # @endif
00661   #
00662   # void init(coil::Properties& prop);
00663   def init(self, prop):
00664     self._rtcout.RTC_TRACE("init()")
00665 
00666     self._properties.mergeProperties(prop)
00667 
00668     num = [-1]
00669     if not OpenRTM_aist.stringTo([num], 
00670                                  self._properties.getProperty("connection_limit","-1")):
00671       self._rtcout.RTC_ERROR("invalid connection_limit value: %s", 
00672                              self._properties.getProperty("connection_limit"))
00673 
00674     self.setConnectionLimit(num[0])
00675 
00676 
00677   ##
00678   # @if jp
00679   #
00680   # @brief Provider を登録する
00681   #
00682   # この Port において提供したいサーバントをこの Port に対して登録す
00683   # る。サーバントは、引数で与えられる instance_name, type_name を、
00684   # サーバント自身のインスタンス名およびタイプ名として、サーバントに
00685   # 関連付けられる。この関数により、サーバントは CorbaPort 内部に保
00686   # 持されるとともに、PortInterfaceProfile にRTC::PROVIDED インター
00687   # フェースとして登録される。
00688   #
00689   # @param instance_name サーバントのインスタンス名
00690   # @param type_name サーバントのタイプ名
00691   # @param provider CORBA サーバント
00692   #
00693   # @return 既に同名の instance_name が登録されていれば false を返す。
00694   #
00695   # @else
00696   #
00697   # @brief Register the provider
00698   #
00699   # This operation registers a servant, which is provided in this
00700   # Port, to the Port. The servant is associated with
00701   # "instance_name" and "type_name" as the instance name of the
00702   # servant and as the type name of the servant. A given servant
00703   # will be stored in the CorbaPort, and this is registered as
00704   # RTC::PROVIDED interface into the PortInterfaceProfile.
00705   #
00706   # @param instance_name Instance name of servant
00707   # @param type_name Type name of the servant
00708   # @param provider CORBA servant
00709   #
00710   # @return Return false if the same name of instance_name is already 
00711   #         registered.
00712   #
00713   # @endif
00714   #
00715   # bool registerProvider(const char* instance_name, const char* type_name,
00716   #                       PortableServer::RefCountServantBase& provider);
00717   def registerProvider(self, instance_name, type_name, provider):
00718     self._rtcout.RTC_TRACE("registerProvider(instance=%s, type_name=%s)",
00719                            (instance_name, type_name))
00720 
00721     try:
00722       self._providers.append(self.CorbaProviderHolder(type_name,
00723                                                       instance_name,
00724                                                       provider))
00725     except:
00726       self._rtcout.RTC_ERROR("appending provider interface failed")
00727       self._rtcout.RTC_ERROR(OpenRTM_aist.Logger.print_exception())
00728       return False
00729 
00730     
00731     if not self.appendInterface(instance_name, type_name, RTC.PROVIDED):
00732       return False
00733 
00734     return True
00735 
00736 
00737   ##
00738   # @if jp
00739   #
00740   # @brief Consumer を登録する
00741   #
00742   # この Port が要求するサービスのプレースホルダであるコンシューマ
00743   # (Consumer) を登録する。Consumer が関連付けられるサービスのインス
00744   # タンス名およびタイプ名として、引数に instance_name, type_name お
00745   # よび Consumer 自身を与えることにより、内部でこれらが関連付けられ
00746   # る。Port 間の接続 (connect) 時 には、subscribeInterfaces() で述
00747   # べられているルールに基づき、Provider Interface の参照が自動的に
00748   # Consumer にセットされる。
00749   #
00750   # @param instance_name Consumer が要求するサービスのインスタンス名
00751   # @param type_name Consumer が要求するサービスのタイプ名
00752   # @param consumer CORBA サービスコンシューマ
00753   #
00754   # @return 既に同名の instance_name が登録されていれば false を返す。
00755   #
00756   # @else
00757   #
00758   # @brief Register the consumer
00759   #
00760   # This operation registers a consumer, which is a service
00761   # placeholder this port requires. These are associated internally
00762   # with specified instance_name, type_name and Consumer itself to
00763   # the argument as service's instance name and its type name
00764   # associated with Consumer.  The service Provider interface'
00765   # references will be set automatically to the Consumer Interface
00766   # object when connections are established, according to the rules
00767   # that are described at the subscribeInterfaces() function's
00768   # documentation.
00769   #
00770   # @param instance_name Instance name of the service Consumer requires
00771   # @param type_name Type name of the service Consumer requires
00772   # @param consumer CORBA service consumer
00773   #
00774   # @return False would be returned if the same instance_name was registered
00775   #
00776   # @endif
00777   #
00778   # bool registerConsumer(const char* instance_name, const char* type_name,
00779   #                       CorbaConsumerBase& consumer);
00780   def registerConsumer(self, instance_name, type_name, consumer):
00781     self._rtcout.RTC_TRACE("registerConsumer()")
00782 
00783     if not self.appendInterface(instance_name, type_name, RTC.REQUIRED):
00784       return False
00785     
00786     self._consumers.append(self.CorbaConsumerHolder(type_name,
00787                                                     instance_name,
00788                                                     consumer,
00789                                                     self))
00790     return True
00791 
00792 
00793   ##
00794   # @if jp
00795   #
00796   # @brief Port の全てのインターフェースを activates する
00797   #
00798   # Port に登録されている全てのインターフェースを activate する。
00799   #
00800   # @else
00801   #
00802   # @brief Activate all Port interfaces
00803   #
00804   # This operation activate all interfaces that is registered in the
00805   # ports.
00806   #
00807   # @endif
00808   #
00809   # void CorbaPort::activateInterfaces()
00810   def activateInterfaces(self):
00811     for provider in self._providers:
00812       provider.activate()
00813 
00814     return
00815 
00816 
00817   ##
00818   # @if jp
00819   #
00820   # @brief 全ての Port のインターフェースを deactivates する
00821   #
00822   # Port に登録されている全てのインターフェースを deactivate する。
00823   #
00824   # @else
00825   #
00826   # @brief Deactivate all Port interfaces
00827   #
00828   # This operation deactivate all interfaces that is registered in the
00829   # ports.
00830   #
00831   # @endif
00832   #
00833   # void CorbaPort::deactivateInterfaces()
00834   def deactivateInterfaces(self):
00835     for provider in self._providers:
00836       provider.deactivate()
00837 
00838     return
00839 
00840 
00841 
00842   ##
00843   # @if jp
00844   #
00845   # @brief Provider Interface 情報を公開する
00846   #
00847   # この Port が所有する Provider インターフェースに関する情報を
00848   # ConnectorProfile::properties に代入し他の Port に対して公開する。
00849   # 今、RTCのインスタンス名等の情報が以下の通りであるとして、
00850   #
00851   # - RTCインスタンス名:              rtc_iname
00852   # - ポート名:                       port_name
00853   # - インターフェース極性:           if_polarity
00854   # - インターフェース型名:           if_tname
00855   # - インターフェースインスタンス名: if_iname
00856   #
00857   # NameValue 型の ConnectorProfile::properties の name と value として
00858   # 以下のものが格納される。
00859   #
00860   # - name
00861   #   <rtc_iname>.port.<port_name>.provided.<if_tname>.<if_iname>
00862   # - value
00863   #   Provider インターフェースの IOR 文字列 
00864   # 
00865   # なお、旧バージョンとの互換性のため以下の表記の NameValue も同時
00866   # に格納されるが、将来のバージョンでは削除される可能性がある。
00867   # 
00868   # - name
00869   #   port.<if_tname>.<if_iname>
00870   # - value
00871   #   Provider インターフェースの IOR 文字列
00872   #
00873   # これらの値は ConnectorProfile::properties に格納され、他のポートに対して
00874   # 伝達される。他の Port でこのインターフェースを使用する Consumer が
00875   # 存在すれば、ConnectorProfile からこのキーからオブジェクトリファレンスを
00876   # 取得し何らかの形で使用される。
00877   #
00878   # @param connector_profile コネクタプロファイル
00879   # @return ReturnCode_t 型のリターンコード
00880   #
00881   # @else
00882   #
00883   # @brief Publish information about interfaces
00884   #
00885   # This operation publishes Provider interfaces information, which
00886   # is owned by this port, to the other Ports via
00887   # ConnectorProfile::properties.
00888   # Now it is assumed RTC instance name and other information is as follows,
00889   #
00890   # - RTC instance name:              rtc_iname
00891   # - Port name:                      port_name
00892   # - Interface polarity:             if_polarity
00893   # - Interface type name:            if_tname
00894   # - Interface instance name:        if_iname
00895   #
00896   # the following values are stored as the "name" and the "value"
00897   # of the NameValue typee element in ConnectorProfile::properties.
00898   #
00899   # - name
00900   #   <rtc_iname>.port.<port_name>.provided.<if_tname>.<if_iname>
00901   # - value
00902   #   IOR string value of interface reference
00903   # 
00904   # In addition, although the following NameValue values are also
00905   # stored for the backward compatibility, this will be deleted in
00906   # the future version.
00907   #
00908   # - name
00909   #   port.<if_tname>.<if_iname>
00910   # - value
00911   #   IOR string value of interface reference
00912   #
00913   # These values are stored in the ConnectorProfile::properties and
00914   # are propagated to the other Ports. If the Consumer interface
00915   # exists that requires this Provider interface, it will retrieve
00916   # reference from the ConnectorProfile and utilize it.
00917   #
00918   # @param connector_profile Connector profile
00919   # @return The return code of ReturnCode_t type
00920   #
00921   # @endif
00922   #
00923   # virtual ReturnCode_t
00924   #    publishInterfaces(ConnectorProfile& connector_profile);
00925   def publishInterfaces(self, connector_profile):
00926     self._rtcout.RTC_TRACE("publishInterfaces()")
00927 
00928     returnvalue = self._publishInterfaces()
00929 
00930     if returnvalue != RTC.RTC_OK:
00931       return returnvalue
00932 
00933     properties = []
00934     for provider in self._providers:
00935       #------------------------------------------------------------
00936       # new version descriptor
00937       # <comp_iname>.port.<port_name>.provided.<type_name>.<instance_name>
00938       newdesc = self._profile.name[:len(self._ownerInstanceName)] + \
00939           ".port" +  self._profile.name[len(self._ownerInstanceName):]
00940       newdesc += ".provided." + provider.descriptor()
00941 
00942       properties.append(OpenRTM_aist.NVUtil.newNV(newdesc, provider.ior()))
00943 
00944       #------------------------------------------------------------
00945       # old version descriptor
00946       # port.<type_name>.<instance_name>
00947       olddesc = "port." + provider.descriptor()
00948       properties.append(OpenRTM_aist.NVUtil.newNV(olddesc, provider.ior()))
00949 
00950     OpenRTM_aist.CORBA_SeqUtil.push_back_list(connector_profile.properties, properties)
00951     
00952     return RTC.RTC_OK
00953 
00954 
00955   ##
00956   # @if jp
00957   #
00958   # @brief Provider Interface 情報を取得する
00959   #
00960   # この Portが所有する Consumer Interface に適合する Provider
00961   # Interface に関する情報をConnectorProfile::properties から抽出し
00962   # Consumer Interface にオブジェクト参照をセットする。
00963   #
00964   # 今、RTC のインスタンス名や Consumer Interface 等の情報が以下のと
00965   # おりであると仮定すると、
00966   #
00967   # - RTCインスタンス名:              rtc_iname
00968   # - ポート名:                       port_name
00969   # - インターフェース極性:           if_polarity
00970   # - インターフェース型名:           if_tname
00971   # - インターフェースインスタンス名: if_iname
00972   #
00973   # この Consumer Interface を表すインターフェース指定子は以下のよう
00974   # に表される。
00975   #
00976   # <rtc_iname>.port.<port_name>.required.<if_tname>.<if_iname>
00977   #
00978   # この関数は、まず引数 ConnectorProfile::properties に上記インター
00979   # フェース指定子をキーとして格納されている Provider Interface 指定
00980   # 子を探し出す。さらに、その Provider Interface 指定子をキーとして
00981   # 格納されている Provider Interface の参照を表す IOR 文字列を取得
00982   # し、Consumer Interface にセットする。
00983   #
00984   # 今、仮に、Provider を prov(n), その参照をIOR(n) さらに Consumer
00985   # をcons(n) のように記述し、これらすべてのインターフェースの型が同
00986   # 一であり、ConnectorProfile に以下の値が設定されているとする。
00987   #
00988   # <pre>
00989   # ConnectorProfile::properties =
00990   # {
00991   #   prov0: IOR0,
00992   #   prov1: IOR1,
00993   #   prov2: IOR2,
00994   #   cons0: prov2,
00995   #   cons1: prov1,
00996   #   cons2: prov0
00997   # }
00998   # </pre>
00999   #
01000   # このとき、cons(0..2) にはそれぞれ、参照が以下のようにセットされる。
01001   #
01002   # <pre>
01003   #   cons0 = IOR2
01004   #   cons1 = IOR1
01005   #   cons2 = IOR0
01006   # </pre>
01007   #
01008   # なお、旧バージョンとの互換性のため、
01009   # ConnectorProfile::properties に Consumer Interface をキーとした
01010   # 値がセットされていない場合でも、次のルールが適用される。
01011   #
01012   # 今、仮に Consumer Interface が
01013   #
01014   # <pre>
01015   #  PortInterfaceProfile
01016   #  {
01017   #    instance_name = "PA10_0";
01018   #    type_name     = "Manipulator";
01019   #    polarity      = REQUIRED;
01020   #  }
01021   # </pre>
01022   #
01023   # として登録されていれば、他の Port の
01024   #
01025   # <pre>
01026   #  PortInterfaceProfile
01027   #  {
01028   #    instance_name = "PA10_0";
01029   #    type_name     = "Manipulator";
01030   #    polarity      = PROVIDED;
01031   #  }
01032   # </pre> 
01033   #
01034   # として登録されている Serivce Provider のオブジェクト参照を探し、
01035   # Consumer にセットする。実際には、ConnectorProfile::properties に
01036   #
01037   # <pre>
01038   # NameValue = { "port.Manipulator.PA10_0": <Object reference> }
01039   # </pre>
01040   #
01041   # として登録されている NameValue を探し、そのオブジェクト参照を
01042   # Consumer にセットする。
01043   #
01044   # @param connector_profile コネクタプロファイル
01045   # @return ReturnCode_t 型のリターンコード
01046   #
01047   # @else
01048   #
01049   # @brief Subscribe to interface
01050   #
01051   # Retrieve information associated with Provider matches Consumer
01052   # owned by this port and set the object reference to Consumer.
01053   #
01054   # Now, Consumer is registered as the following:
01055   # <pre>
01056   #  PortInterfaceProfile
01057   #  {
01058   #    instance_name = "PA10_0";
01059   #    type_name     = "Manipulator";
01060   #    polarity      = REQUIRED;
01061   #  }
01062   # </pre>
01063   # Find the object reference of Serivce Provider that is registered as
01064   # the following of other ports:
01065   # <pre>
01066   #  PortInterfaceProfile
01067   #  {
01068   #    instance_name = "PA10_0";
01069   #    type_name     = "Manipulator";
01070   #    polarity      = PROVIDED;
01071   #  }
01072   # </pre> 
01073   # and set to Consumer.
01074   # In fact, find NameValue that is registered as the following to 
01075   # ConnectorProfile::properties:
01076   # <pre>
01077   # NameValue = { "port.Manipulator.PA10_0": <Object reference> }
01078   # </pre>
01079   # and set the object reference to Consumer.
01080   #
01081   # @param connector_profile Connector profile
01082   #
01083   # @return The return code of ReturnCode_t type
01084   #
01085   # @endif
01086   #
01087   # virtual ReturnCode_t
01088   #   subscribeInterfaces(const ConnectorProfile& connector_profile);
01089   def subscribeInterfaces(self, connector_profile):
01090     self._rtcout.RTC_TRACE("subscribeInterfaces()")
01091     nv = connector_profile.properties
01092 
01093     strict = False # default is "best_effort"
01094     index = OpenRTM_aist.NVUtil.find_index(nv, "port.connection.strictness")
01095     if index >=  0:
01096       strictness = str(any.from_any(nv[index].value, keep_structs=True))
01097       if "best_effort" == strictness:
01098         strict = False
01099       elif "strict" == strictness:
01100         strict = True
01101 
01102       self._rtcout.RTC_DEBUG("Connetion strictness is: %s",strictness)
01103 
01104     for consumer in self._consumers:
01105       ior = []
01106       if self.findProvider(nv, consumer, ior) and len(ior) > 0:
01107         self.setObject(ior[0], consumer)
01108         continue
01109 
01110       ior = []
01111       if self.findProviderOld(nv, consumer, ior) and len(ior) > 0:
01112         self.setObject(ior[0], consumer)
01113         continue
01114 
01115       # never come here without error
01116       # if strict connection option is set, error is returned.
01117       if strict:
01118         self._rtcout.RTC_ERROR("subscribeInterfaces() failed.")
01119         return RTC.RTC_ERROR
01120 
01121     self._rtcout.RTC_TRACE("subscribeInterfaces() successfully finished.")
01122 
01123     return RTC.RTC_OK
01124 
01125 
01126   ##
01127   # @if jp
01128   #
01129   # @brief Interface への接続を解除する
01130   #
01131   # 与えられた ConnectorProfile に関連する Consumer にセットされた
01132   # すべての Object を解放し接続を解除する。
01133   #
01134   # @param self
01135   # @param connector_profile コネクタプロファイル
01136   #
01137   # @else
01138   #
01139   # @brief Unsubscribe interfaces
01140   #
01141   # Release all Objects that was set in Consumer associated with the given 
01142   # ConnectorProfile.
01143   # 
01144   # @param connector_profile Connector profile
01145   #
01146   # @endif
01147   #  virtual void
01148   #    unsubscribeInterfaces(const ConnectorProfile& connector_profile);
01149   def unsubscribeInterfaces(self, connector_profile):
01150     self._rtcout.RTC_TRACE("unsubscribeInterfaces()")
01151     nv = connector_profile.properties
01152 
01153     for consumer in self._consumers:
01154       ior = []
01155       if self.findProvider(nv, consumer, ior) and len(ior) > 0:
01156         self._rtcout.RTC_DEBUG("Correspoinding consumer found.")
01157         self.releaseObject(ior[0], consumer)
01158         continue
01159 
01160       ior = []
01161       if self.findProviderOld(nv, consumer, ior) and len(ior) > 0:
01162         self._rtcout.RTC_DEBUG("Correspoinding consumer found.")
01163         self.releaseObject(ior[0], consumer)
01164         continue
01165 
01166     return
01167 
01168 
01169   ##
01170   # @if jp
01171   # @brief Consumer に合致する Provider を NVList の中から見つける
01172   #
01173   # NVList 中から CorbaConsumerHolder に保持されている Consumer に合
01174   # 致するキーを持つ Provider を見つけ、IOR を抽出しナローイングして
01175   # Consumer にセットする。対応するキーが存在しない、IOR が見つから
01176   # ない、ナローイングに失敗した場合、false を返す。
01177   #
01178   # @param nv Provider が含まれている ConnectorProfile::properties の NVList
01179   # @param cons Provider と対応する Consumer のホルダ
01180   # 
01181   # @retrun bool Consumer に対応する Provider が見つからない場合 false
01182   #
01183   # @else
01184   # @brief Find out a provider corresponding to the consumer from NVList
01185   #
01186   # This function finds out a Provider with the key that is matched
01187   # with Cosumer's name in the CorbaConsumerHolder, extracts IOR
01188   # and performs narrowing into the Consumer and set it to the
01189   # Consumer. False is returned when there is no corresponding key
01190   # and IOR and the narrowing failed.
01191   #  
01192   # @param nv NVlist of ConnectorProfile::properties that includes Provider
01193   # @param cons a Consumer holder to be matched with a Provider
01194   # 
01195   # @return bool false is returned if there is no provider for the consumer
01196   #
01197   # @endif
01198   #
01199   # virtual bool findProvider(const NVList& nv, 
01200   #                           CorbaConsumerHolder& cons,
01201   #                           std::string& iorstr);
01202   def findProvider(self, nv, cons, iorstr):
01203     # new consumer interface descriptor
01204     newdesc = self._profile.name[:len(self._ownerInstanceName)] + \
01205         ".port" +  self._profile.name[len(self._ownerInstanceName):]
01206     newdesc += ".required." + cons.descriptor()
01207 
01208     # find a NameValue of the consumer
01209     cons_index = OpenRTM_aist.NVUtil.find_index(nv, newdesc)
01210     if cons_index < 0:
01211       return False
01212 
01213     provider = str(any.from_any(nv[cons_index].value, keep_structs=True))
01214     if not provider:
01215       self._rtcout.RTC_WARN("Cannot extract Provider interface descriptor")
01216       return False
01217 
01218     # find a NameValue of the provider
01219     prov_index = OpenRTM_aist.NVUtil.find_index(nv, provider)
01220     if prov_index < 0:
01221       return False
01222 
01223     ior_ = str(any.from_any(nv[prov_index].value, keep_structs=True))
01224     if not ior_:
01225       self._rtcout.RTC_WARN("Cannot extract Provider IOR string")
01226       return False
01227  
01228     if isinstance(iorstr, list):
01229       iorstr.append(ior_)
01230 
01231     self._rtcout.RTC_ERROR("interface matched with new descriptor: %s", newdesc)
01232 
01233     return True
01234 
01235 
01236   ##
01237   # @if jp
01238   # @brief Consumer に合致する Provider を NVList の中から見つける
01239   #
01240   # この関数は、古いバージョンの互換性のための関数である。
01241   #
01242   # NVList 中から CorbaConsumerHolder に保持されている Consumer に合
01243   # 致するキーを持つ Provider を見つける。対応するキーが存在しない、
01244   # IOR が見つからない場合、false を返す
01245   #  
01246   # @param nv Provider が含まれている ConnectorProfile::properties の NVList
01247   # @param cons Provider と対応する Consumer のホルダ
01248   # @param iorstr 見つかったIOR文字列を格納する変数
01249   # 
01250   # @retrun bool Consumer に対応する Provider が見つからない場合 false
01251   #
01252   # @else
01253   # @brief Find out a provider corresponding to the consumer from NVList
01254   #
01255   # This function is for the old version's compatibility.
01256   #
01257   # This function finds out a Provider with the key that is matched
01258   # with Cosumer's name in the CorbaConsumerHolder and extracts
01259   # IOR.  False is returned when there is no corresponding key and
01260   # IOR.
01261   #  
01262   # @param nv NVlist of ConnectorProfile::properties that includes Provider
01263   # @param cons a Consumer holder to be matched with a Provider
01264   # @param iorstr variable which is set IOR string
01265   # 
01266   # @return bool false is returned if there is no provider for the consumer
01267   #
01268   # @endif
01269   #
01270   # virtual bool findProviderOld(const NVList&nv,
01271   #                              CorbaConsumerHolder& cons,
01272   #                              std::string& iorstr);
01273   def findProviderOld(self, nv, cons, iorstr):
01274     # old consumer interface descriptor
01275     olddesc = "port." + cons.descriptor()
01276 
01277     # find a NameValue of the provider same as olddesc
01278     index = OpenRTM_aist.NVUtil.find_index(nv, olddesc)
01279     if index < 0:
01280       return False
01281 
01282     ior_ = str(any.from_any(nv[index].value, keep_structs=True))
01283     if not ior_:
01284       self._rtcout.RTC_WARN("Cannot extract Provider IOR string")
01285       return False
01286 
01287     if isinstance(iorstr, list):
01288       iorstr.append(ior_)
01289 
01290     self._rtcout.RTC_ERROR("interface matched with old descriptor: %s", olddesc)
01291 
01292     return True
01293 
01294 
01295   ##
01296   # @if jp
01297   # @brief Consumer に IOR をセットする
01298   #
01299   # IOR をナローイングしてConsumer にセットする。ナローイングに失敗
01300   # した場合、false を返す。ただし、IOR文字列が、nullまたはnilの場合、
01301   # オブジェクトに何もセットせずに true を返す。
01302   #
01303   # @param ior セットする IOR 文字列
01304   # @param cons Consumer のホルダ
01305   # 
01306   # @retrun bool Consumer へのナローイングに失敗した場合 false
01307   #
01308   # @else
01309   # @brief Setting IOR to Consumer
01310   #
01311   # This function performs narrowing into the Consumer and set it to the
01312   # Consumer. False is returned when the narrowing failed. But, if IOR
01313   # string is "null" or "nil", this function returns true.
01314   #  
01315   # @param ior IOR string
01316   # @param cons Consumer holder
01317   # 
01318   # @retrun bool false if narrowing failed.
01319   #
01320   # @endif
01321   #
01322   # bool setObject(const std::string& ior, CorbaConsumerHolder& cons);
01323   def setObject(self, ior, cons):
01324     # if ior string is "null" or "nil", ignore it.
01325     if "null" == ior:
01326       return True
01327 
01328     if "nil"  == ior:
01329       return True
01330 
01331     # IOR should be started by "IOR:"
01332     if "IOR:" != ior[:4]:
01333       return False
01334 
01335     # set IOR to the consumer
01336     if not cons.setObject(ior):
01337       self._rtcout.RTC_ERROR("Cannot narrow reference")
01338       return False
01339 
01340     self._rtcout.RTC_TRACE("setObject() done")
01341     return True
01342 
01343   ##
01344   # @if jp
01345   # @brief Consumer のオブジェクトをリリースする
01346   #
01347   # Consumer にセットされた参照をリリースする。ConsumerのIORが与えら
01348   # れたIOR文字列と異なる場合、falseを返す。
01349   #
01350   # @param ior セットする IOR 文字列
01351   # @param cons Consumer のホルダ
01352   # 
01353   # @retrun ConsumerのIORが与えられたIOR文字列と異なる場合、falseを返す。
01354   #
01355   # @else
01356   # @brief Releasing Consumer Object
01357   #
01358   # This function releases object reference of Consumer. If the
01359   # given IOR string is different from Consumer's IOR string, it
01360   # returns false.
01361   #  
01362   # @param ior IOR string
01363   # @param cons Consumer holder
01364   # 
01365   # @retrun bool False if IOR and Consumer's IOR are different
01366   #
01367   # @endif
01368   #
01369   # bool releaseObject(const std::string& ior, CorbaConsumerHolder& cons);
01370   def releaseObject(self, ior, cons):
01371     if ior == cons.getIor():
01372       cons.releaseObject()
01373       self._rtcout.RTC_DEBUG("Consumer %s released.", cons.descriptor())
01374       return True
01375 
01376     self._rtcout.RTC_WARN("IORs between Consumer and Connector are different.")
01377     return False
01378 
01379   ##
01380   # @if jp
01381   # @class CorbaProviderHolder
01382   # @brief Provider の情報を格納する構造体
01383   #
01384   # CORBA Provider のホルダクラス
01385   #
01386   # @else
01387   # @class CorbaProviderHolder
01388   # @brief The structure to be stored Provider information.
01389   #
01390   # CORBA Provider holder class
01391   #
01392   # @endif
01393   class CorbaProviderHolder:
01394     # CorbaProviderHolder(const char* type_name,
01395     #                     const char* instance_name,
01396     #                     PortableServer::RefCountServantBase* servant)
01397     def __init__(self, type_name, instance_name, servant):
01398       self._typeName = type_name
01399       self._instanceName = instance_name
01400       self._servant = servant
01401       _mgr = OpenRTM_aist.Manager.instance()
01402       self._oid = _mgr.getPOA().servant_to_id(self._servant)
01403 
01404       obj = _mgr.getPOA().id_to_reference(self._oid)
01405       self._ior = _mgr.getORB().object_to_string(obj)
01406       self.deactivate()
01407       return
01408 
01409     def __del__(self):
01410       self.deactivate()
01411       
01412     # std::string instanceName() { return m_instanceName; }
01413     def instanceName(self):
01414       return self._instanceName
01415 
01416     # std::string typeName() { return m_typeName; }
01417     def typeName(self):
01418       return self._typeName
01419 
01420     # std::string ior() { return m_ior; }
01421     def ior(self):
01422       return self._ior
01423 
01424     # std::string descriptor() { return m_typeName + "." + m_instanceName; }
01425     def descriptor(self):
01426       return self._typeName + "." + self._instanceName
01427 
01428     # void activate()
01429     def activate(self):
01430       try:
01431         OpenRTM_aist.Manager.instance().getPOA().activate_object_with_id(self._oid, self._servant)
01432       except:
01433         print OpenRTM_aist.Logger.print_exception()
01434       return
01435 
01436     # void deactivate()
01437     def deactivate(self):
01438       try:
01439         OpenRTM_aist.Manager.instance().getPOA().deactivate_object(self._oid)
01440       except:
01441         print OpenRTM_aist.Logger.print_exception()
01442       return
01443     
01444 
01445   ##
01446   # @if jp
01447   # @brief Consumer の情報を格納する構造体
01448   # @else
01449   # @brief The structure to be stored Consumer information.
01450   # @endif
01451   #
01452   class CorbaConsumerHolder:
01453     # CorbaConsumerHolder(const char* type_name,
01454     #                     const char* instance_name,
01455     #                     CorbaConsumerBase* consumer,
01456     #                     string& owner)
01457     def __init__(self, type_name, instance_name, consumer, owner):
01458       self._typeName = type_name
01459       self._instanceName = instance_name
01460       self._consumer = consumer
01461       self._owner = owner
01462       self._ior = ""
01463       return
01464 
01465     # std::string instanceName() { return m_instanceName; }
01466     def instanceName(self):
01467       return self._instanceName
01468 
01469     # std::string typeName() { return m_typeName; }
01470     def typeName(self):
01471       return self._typeName
01472 
01473     # std::string descriptor() { return m_typeName + "." + m_instanceName; }
01474     def descriptor(self):
01475       return self._typeName + "." + self._instanceName
01476 
01477     ##
01478     # @if jp
01479     # @brief Consumer に IOR をセットする
01480     # @else
01481     # @brief Setting IOR to Consumer
01482     #@endif
01483     #
01484     # bool setObject(const char* ior)
01485     def setObject(self, ior):
01486       self._ior = ior
01487       orb = OpenRTM_aist.Manager.instance().getORB()
01488       obj = orb.string_to_object(ior)
01489       if CORBA.is_nil(obj):
01490         return False
01491 
01492       return self._consumer.setObject(obj)
01493 
01494     ##
01495     # @if jp
01496     # @brief Consumer のオブジェクトをリリースする
01497     # @else
01498     # @brief Releasing Consumer Object
01499     # @endif
01500     #
01501     # void releaseObject()
01502     def releaseObject(self):
01503       self._consumer.releaseObject()
01504       return
01505 
01506     # const std::string& getIor()
01507     def getIor(self):
01508       return self._ior
01509 
01510 
01511   ##
01512   # @if jp
01513   # @brief ConnectorProfile と Consuemr の比較をしオブジェクト参照を
01514   #        セットするための Functor
01515   # @else
01516   # @brief Subscription mutching functor for Consumer
01517   # @endif
01518   class subscribe:
01519     def __init__(self, cons):
01520       self._cons = cons
01521       self._len  = len(cons)
01522 
01523     def __call__(self, nv):
01524       for i in range(self._len):
01525         name_ = nv.name
01526         if self._cons[i].descriptor() == name_:
01527           try:
01528             obj = any.from_any(nv.value, keep_structs=True)
01529             self._cons[i].setObject(obj)
01530           except:
01531             print OpenRTM_aist.Logger.print_exception()
01532 
01533 
01534 
01535   ##
01536   # @if jp
01537   # @brief Consumer のオブジェクトを解放するための Functor
01538   # @else
01539   # @brief Functor to release Consumer's object
01540   # @endif
01541   class unsubscribe:
01542     def __init__(self, cons):
01543       self._cons = cons
01544       self._len  = len(cons)
01545 
01546     def __call__(self, nv):
01547       for i in range(self._len):
01548         name_ = nv.name
01549         if self._cons[i].descriptor() == name_:
01550           self._cons[i].releaseObject()
01551           return
01552 
01553         # for 0.4.x
01554         if "port."+self._cons[i].descriptor() == name_:
01555           self._cons[i].releaseObject()
01556 
01557 


openrtm_aist_python
Author(s): Shinji Kurihara
autogenerated on Thu Aug 27 2015 14:17:28