"""

    Demo DynamicPolicy használatára.

    Egy H2O instance allapot tulajdonsága "szilárd" vagy "folyékony" lehet(létrehozás után "folyékony").

    Az allapot tulajdonság mindig lekérdezhető, de nem lehet direktben módosítani. A masolj metódus is

    mindig meghívható és a visszadott érték egy új H2O instance lesz az aktuális állapottal.

    A fagyjmeg és az olvadjmeg metódusok csak a megfelelő allapot érték esetén léteznek, azaz pl.

    "szilárd" allapot esetében fagyjmeg hívása "Member not found." hibaüzenetet generál.

"""

import pythoncom

import winerror

import win32com.server.util

from win32com.server.policy import DynamicPolicy

from win32com.server.exception import COMException

import types

class H2O:

    """

        H2O demo class

    """

    #COM regisztrációs információk

    _reg_desc_          = 'H2O demo class'

    _reg_clsid_         = '{3D80E5B1-E619-11D4-BF65-00C0DF0463FE}'

    _reg_progid_        = 'Demo.H2O'

    _reg_verprogid_     = 'Demo.H2O.1'

    _reg_policy_spec_   = 'DynamicPolicy'   # UseCommandLine regisztráció során innen tudja, hogy DynamicPolicy-t szeretnénk

    #Csak az egyszerűség kedvéért a két állapotban elérhető attributumokat/metódusokat

    #kigyűjtöttem két listába

    _szilard_attrs_ = ["olvadjmeg","masolj","allapot"]

    _folyekony_attrs_ = ["fagyjmeg","masolj","allapot"]

    def olvadjmeg(self):

        """

            COM-on keresztül csak "szilárd" állapot esetén hívható

        """

        self.allapot="folyékony"

    def fagyjmeg(self):

        """

            COM-on keresztül csak "folyékony" állapot esetén hívható

        """

        self.allapot="szilárd"

    def masolj(self):

        """

            Ha egy Python class-t szeretnénk visszadni COM-on keresztül,

            akkor wrap hívásával tudunk belőle egy IDispatch interfészt csinálni.

            Meg kell adni a policy-t is, mert az alapértelmezett a DesignatedWrapPolicy.

        """

        return win32com.server.util.wrap(H2O(self.allapot),usePolicy=DynamicPolicy)

        

    def __init__(self,allapot="folyékony"):

        """

            Alapértelmezés szerint "folyékony" lesz(kliens csak ilyet tud csinálni!),

            de a masolj-hoz hasonló metódusokban - ahol egy új példányt ad vissza

            a metódus - lehetőség van "szilárd"/"folyékony" állapotú példány létrehozására.

        """

        self.allapot=allapot

    

    def _dynamic_(self, name, lcid, wFlags, args):

        #nézzük az adott állapotban megengedett attributumokra hivatkozik-e a kliens

        if (self.allapot=="szilárd" and name.lower() not in self._szilard_attrs_) or \

           (self.allapot=="folyékony" and name.lower() not in self._folyekony_attrs_):

            raise COMException("%s nevű attributum nem létezik!" % name, winerror.DISP_E_MEMBERNOTFOUND)

        item = getattr(self,name.lower())   # hogy VB ne kavarjon be itt minden kisbetűs

        if wFlags & pythoncom.DISPATCH_METHOD and type(item) in [types.MethodType]:

            #metódus hívás

            return apply(item,args)

        elif wFlags & pythoncom.DISPATCH_PROPERTYGET:

            # Python kliens először ezzel próbálkozik metódus esetében is

            # Az alábbi exception generálásával bírjuk rá hogy metódusként is

            # megpróbálja elérni(kicsit dinnye, de ez van)

            if type(item) in [types.MethodType]:

                raise COMException("%s metódus nem tulajdonság!" % name, winerror.DISP_E_MEMBERNOTFOUND)

            return item

        elif wFlags & (pythoncom.DISPATCH_PROPERTYPUT | pythoncom.DISPATCH_PROPERTYPUTREF):

            #tulajdosnság beállítás(itt: allapot) nem engedélyezett

            raise COMException("Értékadás %s tulajdonságnak nem engedélyezett!" % name, winerror.E_ACCESSDENIED)

        else:

            raise COMException("invalid wFlags", winerror.E_INVALIDARG)

def Register():

    # szokásos regisztrálás, de a policy nem az alapértelmezett DesignatedWrapPolicy lesz,

    # hanem a H2O class _reg_policy_spec_ attributumában beállított DynamicPolicy

    from win32com.server.register import UseCommandLine

    return UseCommandLine(H2O)

if __name__=='__main__':

    Register()