====== ExtraOperations ====== ExtraOperations su nastroj, ktory umoznuje vykonavat nejake operacie s datami z karty este predtym, ako sa dostanu do aplikacie. Typickym prikladom bolo 'preklapanie' zostatku penazenky v slovenskych korunach na eura. Dalsie priklady pouzitia su blokovanie kariet, internetove plnenie karty, pripadne opravy nekonzistentnych dat na karte. Implementacne to funguje tak, ze ked dorazia data z platobneho do receivera v libechipcard, tak este predtym, ako su delegovane do aplikacie sa najprv prejdu vsetky ExtraOperacie v ExtraOperationManagerovi a nad kazdou sa vola metoda bool IsExtraOperation( EDataCollection* ). Ak niektora z nich vrati true, znamena to, ze ide spracovavat data, k dalsim ExtraOperaciam sa uz nejde a ani data nepokracuju do aplikacie. Dotycna ExtraOperacia si moze vytvorit nejaku dataCol na zapis, poslat, preberie tym na chvilu ulohu receivera, takze odpoved pride jej a potom restorne povodny receiver (odpamatava sa v ExtraOperationManagerovi automaticky) cim znovu posle request na citanie dat. Ked sa karta vycita a dorazia nove data, opat sa prechadzaju vsetky ExtraOperations, takze sa mozu vykonavat postupne. Kazda ExtraOperacia, ktora zapisuje na kartu by si mala zabezpecit, aby na nu zapisovala iba raz, inak samozrejme dojde k zacykleniu. \\ Nie je nevyhnutne potrebne, aby ExtraOperation zapisovala na kartu, v takom pripade staci, ak v IsExtraOperation metode porobi co potrebuje a vrati false; Specialny pripad pouzitia je taky, ze vzhladom na to, ze dostava smernik na vycitanu DataCollection, moze v nej nejako modifikovat data, vratit false a tato modifikovana dataCollection potom pokracuje do aplikacie. Je to taky nie prave priamociary sposob, ako nieco robit, preto jeho vyuzitie treba dobre zvazit. Je tak napriklad riesene blokovanie kariet v projekte IDOL - ak ma byt karta zablokovana (zoznam blokovanych kariet), tak sa vo vycitanych datach nastavi priznak blokovana, inak sa nastavi, ze blokovana nie je aj v pripade, ze karta fyzicky blokovana je. \\ Mimochodom, jedna sa o design pattern Chain of responsibility (retaz zodpovednosti). **Vytvorenie vlastnej ExtraOperation nie je zlozite. Staci urobit nasledovne:** \\ - vytvorim si potomka //EM::Devices::ECardExtraOperation//, v pripade, ze sa chystam zapisovat na kartu, tak aj //EBlAppCardRcv// - vo svojom potomkovi pretazim metody: * //virtual bool IsExtraOperation( EDataCollection * )// * //virtual void WriteOK( EPTAnswer*, long )// * //virtual void WriteError( EPTAnswer* , long , bool & )// * podla moznosti spravim virtual aj destruktor - pretazene metody si implementujem - zaregistrujem svoju novu ExtraOperation v managerovi nasledovne: * //EM::Devices::EChipCard::GetInstance().GetCardExtraOperationM()->AddECardExtraOperation( new EMyNewExtraOperation() );// * dobry napad je registrovat vsetky extraOperacie na jednom mieste, preto si dam hladat AddECardExtraOperation po projekte a svoju pridam k ostatnym uz existujucim **Nejake implementacne detailiky** Pretazena metoda WriteOK v pripade, ze som nieco zapisoval na kartu by mohla vyzerat nasledovne: void EMyNewExtraOperation::WriteOK( EPTAnswer* answer, long tag ) { EBlAppCardRcv::WriteOK(answer, tag); // zavolam WriteOK svojho predka EINFO( "WriteOK" ); // zalogujem si, podla mna uzitocny log //TODO zapisem statistiku? //TODO zobrazim nejaku informacnu hlasku? EChipCard::GetInstance().GetCardExtraOperationM()->RestoreOldRcv(); // ROZHODNE restornem stary receiver EGlobEBlIface::GetUi()->setState( mLastAppState ); //vratim nazad odlozeny stav aplikacie (ak som sa v IsExtraOperation prepinal do Busy statu) //TODO nejake upratovanie? } Pretazena metoda WriteError bude podobna: void EMyNewExtraOperation::WriteError( EPTAnswer* answer, long tag, bool &repeat ) { EBlAppCardRcv::WriteError( answer, tag ,repeat ); //zavolam WriteError predka EERROR( "WriteERR" ); //zalogujem si, EERROR je opravneny EChipCard::GetInstance().GetCardExtraOperationM()->RestoreOldRcv(); //ROZHODNE restornem receiver EGlobEBlIface::GetUi()->setState( mLastAppState ); //vratim nazad odlozeny stav aplikacie (ak som sa v IsExtraOperation prepinal do Busy statu) //TODO upratovanie? } Telo metody IsExtraOperation tazko nejako popisat, je to prave miesto, kde kazda ExtraOperation robi, co sa od nej ocakava, bude to nieco ako: bool EMyNewExtraOperation::IsExtraOperation( EDataCollection* dataCollection ) { //checknem podmienku, ci idem nieco robit, ak nie, tak return false; //urobim to, co sa odo mna ocakava :) //ak idem nieco zapisovat aj na kartu, tak mLastAppState = EGlobEBlIface::GetUi()->getState(); //toto nie je nevyhnutne, ale podla mna uzitocne, zmenim stav na Busy a predtym si zapamatam, aky stav som mal, aby som sa k nemu bezpecne vratil na konci zapisu. mLastAppState je moj member. EGlobEBlIface::GetUi()->setState( EUI_HLAVNY::Busy_AppState ); EChipCard::GetInstance().SendAplRequestWrite( this, dataColForWrite ); //poslem data na zapis, prvy paramater je smernik na receiver, cize JA, druhy je dataCol na zapis, co som si pripravil return true; //vraciam true, cim preberam na chvilku reziu pri spracovani karty } Je dobre si do svojej extraOperation napisat nejake logy, ale s tym, ze tento kod sa vykonava pri kazdom prilozeni karty, takze netreba moc floodovat, proste par rozumnych zmysluplnych logov informujucich o tom, ze sa zavolala moja extraOperation, nepresla podmienka ta ta a tak nejde nic robit, alebo idem robit a posielam zapis napr.