Validační server - automatická kontrola semestrálních prací

Struktura XML souborů s popisem procesu

Zpět na hlavní stránku

Na stránce o validačním procesu je uveden obecný popis jak probíhá vlastní fáze validace, je popsán výstup validace a vůbec jakýsi "kontext" validačního procesu. V tomto dokumentu bude podrobně popsán formát XML souborů definujících proces a všechny podporované elementy.

Jak je vidět, soubor silně připomíná konstrukce strukturovaných jazyků. Stejně tak jednotlivé elementy více či méně připomínají jejich příkazy či řídící konstrukce.

Pro komplexní příklad si prohlédněte případovou studii pro předmět KIV/PPA1.

Hlavní element: validation-process

<!ELEMENT validation-process ( cache | call | if | script | while | break | return | 
  continue | error | warning | info| quit | quit-if-error | time-limited )* >
<!ATTLIST validation-process parameters CDATA #IMPLIED >

Všechny příkazy jsou uzavřeny v tomto hlavním elementu. Vzhledem k tomu, že proces může být rozdělen do více XML souborů, umožňuje se předávání parametrů. K tomu slouží atribut 'parameters', ve kterém musí být seznam názvů parametrů, které tento xml soubor očekává. Jednotlivé parametry jsou odděleny čárkou. Tento seznam je pouze informativní pro "klienty" tohoto XML, neprovádí se žádná kontrola, zda jsou parametry zadány.

Hlavní soubor s popisem validačního procesu získává následující parametry, které jsou tedy poté registrované jako stejnojmenné JavaScriptové proměnné a jsou přístupné z jakéhokoliv (i podřízeného) scriptu:

NázevTypPopis
infoValidationInfo Veškeré informace o této validaci
inputFilejava.io.File Validovaný soubor
workDirjava.io.File Pracovní adresář této validace
domainDirjava.io.File Adresář, v němž je uložena aktuální doména
authorjava.lang.String Jméno autora validovaného souboru - bere se ze vstupu validace
autorjava.lang.String Alias pro "author"
localejava.util.Locale Aktuální Locale této validace
loggerorg.apache.log4j.Logger Instance loggeru pro script.
customParametersjava.util.Map Mapa parametrů této validace - validačnímu serveru může být prostřednictvím rozhraní ValidationInput předána mapa libovolných parametrů, které validační script potřebuje.
domainValidationDomain Aktuální validační doména

Element: script

<!ELEMENT script ( #PCDATA ) >

Tento element obsahuje JavaScriptový script. Více informací naleznete na stránce o JavaScriptu. Příklad:

<validation-process>
 
    <script>
    	logger.info("Ahoj svete!");
    	logger.info("Validovany soubor: "+inputFile.getAbsolutePath());
    </script>
 
</validation-process>

Mnoho XML elementů očekává ve svém těle JavaScript (u těchto elementů je to vždy uvedeno zde v dokumentaci). V tom případě již v nich není podelement "script", ale obsahují přímo kód (příkladem je například element "param" hned v následující kapitole). Tyto elementy často očekávají od tohoto JavaScriptu nějakou výslednou hodnotu - předpokládají tedy, že uvedený JavaScript tvoří výraz, který je poté navrácen jako hodnota celého tohoto scriptu. Script může být libovolně rozsáhlý a obsahovat více příkazů/výrazů za sebou, jako hodnota scriptu se pak bere hodnota toho posledního.

Element: call

<!ELEMENT call ( param* ) >
<!ATTLIST call process CDATA #REQUIRED >

<!ELEMENT param ( #PCDATA ) >
<!ATTLIST param name CDATA #REQUIRED >

Jak bylo uvedeno, jednotlivé XML soubory se mohou vzájemně volat. K tomu slouží právě tento element. Jako parametr "process" je uvedena cesta k volanému souboru (a to včetně přípony XML). Cesta může být relativní (vůči aktuálnímu XML) nebo absolutní - absolutní je tehdy, začíná-li znakem "/". Absolutní cesty mají v tomto případě kořen v adresáři "data/domains". XML soubory mohou být tedy umístěny pouze v adresářové struktuře POD adresářem "data/domains".

V adresáři "data/domains/common" jsou připravené některé často používané části kódu, především pak jakési spojky mezi JavaScriptem a API validačního serveru. Následující příklad ukazuje, jak zavolat přeložení jednoho Java souboru:

<validation-process>
 
    <!-- prelozim zaslany Java soubor -->
    <call process="/common/compilejava.xml">
        <param name="file">inputFile</param>
    </call>
 
</validation-process>

Uvnitř elementu "param" se očekává JavaScript, který vrátí hodnotu tohoto parametru. V příkladu tedy script "inputFile" vrátí vstupní soubor validace.

Element: time-limited

<!ELEMENT time-limited ( cache | call | if | script | while | break | return | 
  continue | error | warning | info| quit | quit-if-error | time-limited )* >
<!ATTLIST time-limited time CDATA #REQUIRED
                       exceed-message CDATA #IMPLIED>

Element zapouzdřuje libovolné množství dalších elementů a slouží k omezení maximální možné doby zpracování těchto elementů. Pokud se doba zpracování překročí, okamžitě je zpracování přerušeno a celá validace je ukončena s výstupní chybou "TIMEOUT".

Atribut "time" určuje maximální dobu vykonávání v milisekundách a je interpretován jako JavaScriptový kousek kódu. Může tedy být uvedena konstanta (např. "5000") nebo například JavaScriptová proměnná (např. "mojeVypoctenaDoba"), která je někde před tímto elementem inicializována.

Atribut "exceed-message" obsahuje název řetězce z ResourceBundle domény či serveru, který je zobrazen uživateli v případě, že je doba překročena.

Element: quit, quit-if-error

<!ELEMENT quit EMPTY >
<!ELEMENT quit-if-error EMPTY >

Element "quit" okamžitě ukončí validaci. Klientovi se tedy zašle výsledek validace a veškeré informace, které byly až do této chvíle během validace vyrobeny. Element "quit-if-error" způsobí ukončení pouze tehdy, pokud je již výsledek validace jiný, než "ok".

Element: return

<!ELEMENT return EMPTY >

Element "return" slouí k opuštění aktuálního XML souboru s procesem a k návratu do volajícího XML. Pokud se nachází v hlavním XML domény, má stejný efekt jako volání 'quit'.

Element: cache

<!ELEMENT cache ( file, observed-file+, put ) >
<!ELEMENT put ( cache | call | if | script | while | break | return | 
  continue | error | warning | info| quit | quit-if-error | time-limited )* >
<!ELEMENT observed-file ( #PCDATA ) >
<!ELEMENT file ( #PCDATA ) >

Umožňuje používání interní souborové cache validačního serveru. Tato cache slouží k tomu, aby se zbytečně nevytvářely ty samé soubory stále dokola (například aby se stále nepřekládaly vzorové programy). Začneme ukázkou:

<!-- kompilace vzoroveho programu, pokud uz neni zkompilovan -->
<cache>
    <file>
        vzorClass
    </file>
    <observed-file>
        vzorFile
    </observed-file>
    <put>
 
        <!-- prelozim vzorovy soubor -->
        <call process="/common/compilejava.xml">
            <param name="file">vzorFile</param>
        </call>
 
    </put>
</cache>

V podelementech "file" a "observed-file" jsou JavaScripty, které vždy vracejí požadovanou informaci: "file" označuje soubor, který je cachován. "observed-file" označuje soubor, který slouží jako podklad pro validaci záznamu v cache - záznam v cache je platný do té doby, dokud se "observed-file" nezmění (tj. například učitel nahraje aktualizovanou verzi vzorového příkladu - pak se musí znovu přeložit).

Těchto 'observed-file' může být nadefinováno libovolné množství (uvést více těchto XML elementů za sebou) - poté platí, že záznam v cache je platný dokud jsou všechny tyto soubory nezměněny. Změní-li se alespoň jeden, zneplatní se záznam v cache.

Podelement "put" může obsahovat libovolné příkazy a je aktivován v případě, když požadovaný soubor v cache není či byl-li zrušen. Put tedy slouží k vytvoření cachovaného souboru "file". V našem případě to tedy funguje tak, že při prvním spuštění tohoto příkazu se aktivuje "put" a tedy se přeloží vzorový soubor "vzorFile" (a vznikne tak soubor "vzorClass"). Při další validaci nějakého studentského příkladu (při níž se právě vzorové soubory překládají) se již vzorový soubor nepřekládá.

Element: if

<!ELEMENT if ( condition, then?, else? ) >
<!ELEMENT condition ( #PCDATA ) >
<!ELEMENT then ( cache | call | if | script | while | break | return | 
  continue | error | warning | info | quit | quit-if-error | time-limited )* >
<!ELEMENT else ( cache | call | if | script | while | break | return | 
  continue| error | warning | info| quit | quit-if-error | time-limited )* >

Klasická podmínka: V podelementu "condition" je JavaScript, který musí vracet hodnotu typu boolean. Je-li true, vyvolá se tělo "then", jinak se vyvolá tělo v "else".

Element: while

<!ELEMENT while ( condition, body ) >
<!ELEMENT condition ( #PCDATA ) >
<!ELEMENT body ( cache | call | if | script | while | break | return | 
  continue | error | warning | info| quit | quit-if-error | time-limited )* >
<!ELEMENT break EMPTY >
<!ELEMENT continue EMPTY >

Klasický cyklus while. V podelementu "condition" je JavaScript, který musí vracet hodnotu typu boolean. Dokud je "true", volá se opakovaně tělo "body". Kdekoliv v tomto těle (nebo i "hlouběji") se může vyskytovat příkaz "break" (opuštění nejvnitřnějšího cyklu) nebo příkaz "continue" (návrat k vyhodnocení podmínky cyklu).

Element: error

<!ELEMENT error ( #PCDATA ) >
<!ATTLIST error key CDATA #IMPLIED
          code CDATA #IMPLIED>

Element slouží k uložení chyby do výsledku validace. Pozor, tento element nezpůsobí ukončení validace, pouze přidá další chybu do výsledku! Chcete-li navíc validaci na tomto místě ukončit, uveďte za toto "error" ještě element "<quit/>".

Text chyby je možno uvést dvěma způsoby: Pokud je chyba dopředu známa, je nejlepší její text uvést do ResourceBundle domény, například pod klíčem "moje_chyba" a poté tento klíč uvést jako parametr "key". Pokud je text chyby složitější, je možno text chyby vygenerovat pomocí JavaScriptu - v tom případě neuvádějte parametr "key", ale jako tělo elementu "error" uveďte JavaScript, který pak musí vracet text chyby.

Dále je možno uvést kód chyby, parametrem "code". Buď uveďte přímo číslo chyby tak, jak je definováno v rozhraní ValidationResult nebo uveďte název chyby tak, že uvedete název konstanty z téhož rozhraní bez prefixu "VR_", tedy např:

<error key="moje_chyba" code="COMPILE_ERROR"/>

Druhý způsob je samozřejmě doporučený, vyvarujete se zbytečných chyb a používání číselných konstant, které se teoreticky mohou změnit.

Element: warning, info

<!ELEMENT warning #PCDATA >
<!ATTLIST warning key CDATA #IMPLIED >

<!ELEMENT info #PCDATA >
<!ATTLIST info key CDATA #IMPLIED >

Zcela stejná funkcionalita jako element "error", pouze bez možnosti nastavení chybového kódu. Přidává varování či informaci do výsledku validace.

Zpět na hlavní stránku

autor: Lukáš Valenta, září 2007 (lukas.valenta at seznam.cz)