středa 8. dubna 2015

Shoda reference metody s deklarací metody

Pokud vytvoříme vrchol metody podle deklarace a později při analýze narazíme na volání metody, je potřeba definovat způsob rozpoznání shody této reference metody s deklarací. V opačném případě by měl tento postup fungovat taktéž. Tedy pokud narazíme na volání metody, která ještě nebyla v grafu vytvořena, vytvoří se dočasný uzel pro tuto metodu. Dále při zpracovávání AST této metody je potřeba nalézt dočasný uzel a nahradit ho.

V následujícím textu budou často používané pojmy, které je nutno pro srozumtelnost specifikovat:


1
2
3
4
5
<T> // typovy parametr
<T> void metoda(T) // metoda s typovym parametrem
void metoda(List<String>) // metoda s generickym parametrem
List<T> a // generický datový typ s typovym parametrem
void metoda(String...a) // metoda s proměnlivým parametrem

Podle popisu jazyka Java(1) se propojení volání (resp. reference) metody a deklarace metody provádí ve třech fázích. Pokud propojení neuspěje v jedné fázi pokračuje se další. Nepovede-li se propojení ve třetí fázi, je nahlášena chyba při překladu. V první řadě se však detekuje, zda je metoda potenciálně propojitelná.  Tedy vyhledá se množina aplikovatelných deklarací metod. Tyto potenciální metody musí splňovat všechny následující kritéria:
  • identické názvy reference a deklarace metody,
  • blok kódu volající metodu musí mít patřičný přístup k deklaraci metody,
  • jestliže má metoda n parametrů se speciálním parametrem určujícím proměnlivý počet parametrů (variable arity method) , musí mít reference na metodu více nebo rovno n-1 parametrů
  • jestliže nemá metoda tento speciální parametr a má n parametrů, potom musí mít reference metody právě n parametrů,
  • jestliže je v referenci metody použitý explicitní typový argument a metoda je generická, potom musí být počet typových parametrů roven počtu typových parametrů metody.
První fáze

V první fázi propojování reference metody s deklaraci vycházíme z množiny potenciálně aplikovatelných metod. Zde se postup větví podle toho, zda je metoda generická, či ne.
Jestliže se jedná o generickou metodu je nutno kontrolovat , zda odpovídají datové typy parametru, které nemají generický datový typ a dále zda lze generický typ navázat na datový typ z volání metody.
Jestliže se naopak nejedná o generickou metodu, je propojení možné, pokud jsou parametry referencované metody stejného datového typu, jako deklarované metody nebo podtypu. Další možností je, že jsou datové typy konvertovatelné.

Jestliže nejsou podmínky první fáze splněny s žádnou deklarací, pokračuje se druhou fází propojení reference metody s deklarací.

Druhá fáze

Tato fáze se na rozdíl od první pokouší o explicitní konverzi parametrů, pokud nejsou generické. V případě parametrů s generickým datovým typem je postup stejný

Třetí fáze

Poslední fáze spočívá v propojování metod, které mají proměnlivý počet parametrů. Detekce propojení je založena na předchozích fázích. Navíc je mezi podmínkami možnost výskytu tohoto parametru umožňující proměnlivý počet parametrů.

V případě parametrů s negenerickým datovým typem je potřeba při vytváření dočasných vrcholů metod v grafu vytvořit tento uzel s již konvertovanými typy. Tuto možnost nám poskytuje knihovna Procyon, díky které při volání metody můžeme získat výsledný datový typ konverze typu parametru. Pokud později narazíme na deklaraci metody, může již porovnání probíhat pomocí uložených datových typů. Pokud bude vytváření vrcholů probíhat v opačném pořadí, opět bude potřeba srovnávat parametry vrcholu deklarované metody s konečným datovým typem parametrů referencované metody.

Neboť je možné za typové parametry dosadit jakýkoliv typ, bude při hledání shody metod porovnání libovolného typu s typovým parametrem vždy označováno jako shodné. Detekce špatného přiřazení typu do parametru se nebude provádět. Předpokládá se, že kompilátor provedl bezchybný převod do bajtkódu.

Protože knihovna Procyon pracuje s proměnlivým parametrem jako s polem a v případě volání metody s tímto proměnlivým parametrem dokáže rovnou tvrdit, že je poslední parametr pole, je práce s voláním metody stejná, jakoby se na poslední pozici vyskytovalo pole odpovídajícího datového typu. Tedy práce s touto metodou se nebude nijak lišit oproti práce s jinými metodami.

Shrnutí

Propojení volané metody s deklarací metody bude probíhat na základě následujících bodů:
  • shodné jmého metody,
  • shodný počet parametrů,
  • shodný datový typ všech parametrů,
    • typový parametr bude označen jako shodný s libovolným typem,
    • generické parametry se shodným hlavním typem (např.: List, Map) , ale rozdílnými typovými parametry budou taktéž označeny jako shodné.

Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2

pondělí 6. dubna 2015

Uložení anotace jako grafu

Anotace je modifikátor, který obsahuje název anotačního typu a dále může obsahovat nula nebo více párů názvu alementu a jeho hodnoty. Tento modifikátor je možné použít při deklaraci balíku, třídy, výčtu, rozhraní, anotačního typu, atributu, metody, parametru, konstrktoru a lokálních proměnných.

Gramatika anotace je v dokumentaci Java popsána následovně:
Annotations:
    Annotation
    Annotations Annotation

Annotation:
    NormalAnnotation
    MarkerAnnotation
    SingleElementAnnotation

Z popisu gramatiky anotace je zřejmé, že každý element může být anotován i více anotacemi. Dále gramatika popisuje tři druhy anotací: klasickou anotaci, indikátorovou anotaci a jednoelementovou anotaci.

Pro interpretaci anotace v grafu je nutno zavést dva nové vrcholy. Prvním vrcholem bude vrchol anotace, který nebude obsahovat žádnou vlastnost. Naproti tomu bude nutno pro tento vrchol vytvořit vztah vedoucí k odpovídajícímu anotačnímu typu. Vzhledem tomu, že se jedná o typ bude tento vztah nazván stejně jako vztah určující datový typ a to is_type. Dále bude možnost vytvořit nula nebo více vztahů s uzlem zachycujícím hodnotu elementu anotace. Vrchol hodnoty bude mít jedinou vlastnost. Tato vlastnost bude nazvána value a bude zaznamenávat nově nastavenou hodnotu elementu. S vrcholem elementu, se kterým je přiřazena hodnota, bude tento vrchol spjat vztahem s názvem is_value_of. Následuje shrnutí popsaných vrcholů.

Shrnutí anotace
Vlastnosti:
  • nic
Vztahy:
  • is_type (Anotační typ)
  • have_element (Hodnota)

Shrnutí hodnoty
Vlastnosti:
  • value (String)
Vztahy:
  • is_value_of (Metoda)

Nyní si projdeme 3 možné druhy anotování a vytvoříme pro každý druh demonstrační příklad s předvedením uložení v grafové databázi.

Klasická anotace (NormalAnnotation)

Klasická anotace má v dokumentaci nejobsáhlejší popis gramatiky oprotiostatním anotacím. Ukážem si jenom část z tohoto popisu.
NormalAnnotation:
    @ TypeName ( ElementValuePairsopt )

ElementValuePairs:
    ElementValuePair
    ElementValuePairs , ElementValuePair

ElementValuePair:
    Identifier = ElementValue

ElementValue:
    ConditionalExpression
    Annotation
    ElementValueArrayInitializer
U tohoto druhu anotace je tedy možné vypisovat páry element a hodnota, kde hodnota může obsahovat podmíněný výraz, anotaci, hodnotu či pole hodnot. Tyto páry se vepisují do kulatých závorek a je možné jich zadat nula a více.

Jako příklad si prvně nadeklarujeme anotační typ AnotType, který budeme v následujících příkladech anotací využívat.


1
2
3
4
5
package test_package;
public @interface AnotType {
 int[] element1 () default {1,2};
 String element2() default "hodnota";
}

Nyní vytvoříme příklad klasické anotace.


1
2
3
4
5
6
package test_package;
public class Anotovana {
 @AnotType(element2="jina_hodnota", element1={3,4}) String metoda(){
  return "nic";
 }
}

Závěrem si ukážeme odpovídající graf reprezentující předchozí kód.




Indikátorová anotace (MarkerAnnotation)

Dalším druhem anotace je indikátorová anotace,která je pro změnu nejjednodušší. Jediné, co se při této anotaci uvádí je název anotačního typu. Programátor se tak spoléhá na defaultní hodnoty uvedené při deklaraci anotačního typu. V tomto případě bude příklad kódu a odpovídajícího grafu vypadat následovně:


1
2
3
4
5
6
package test_package;
public class Anotovana {
 @AnotType String metoda(){
  return "nic";
 }
}



Jednoelementová anotace (SingleElementAnnotation)

Posledním způsobem anotace je zjenodušení klascké anotace. Pokud tedy máme anotační typ s právě jedním elementem, jehož název je "value", potom při anotaci není potřeba název tohoto elementu uvádět.

Pro příklad je nutné si prvně vytvořit demonstrativní anotační typ, který bude obsahovat pouze jeden element. Dále potom ukážeme použití tohoto anotačního typu při anotaci.

Anotační typ AnotType:

1
2
3
4
package test_package;
public @interface AnotType {
 String value() default "hodnota";
}

Použití anotačního typu:

1
2
3
4
5
6
package test_package;
public class Anotovana {
 @AnotType("neco") String metoda(){
  return "nic";
 }
}

Odpovídající graf


Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.7

sobota 4. dubna 2015

Uložení anotačního typu jako grafu

V jazyce Java je možné deklarovat speciální druh rozhraní zvaný anotační typ. Tento druh rozhraní se odlišuje od klasické anotace symbolem @, který předchází klíčovému slovu interface, jak je vidět na následujícím popisu gramatiky rozhraní.
AnnotationTypeDeclaration:
    InterfaceModifiersopt @ interface Identifier AnnotationTypeBody

AnnotationTypeBody:
    { AnnotationTypeElementDeclarationsopt }

AnnotationTypeElementDeclarations:
    AnnotationTypeElementDeclaration
    AnnotationTypeElementDeclarations AnnotationTypeElementDeclaration
Dle popisu lze deklaraci anotačního typu začít seznamem modifikátorů, následuje název anotačního typu a na závěr je nutno doplnit tělo deklarace anotačního typu. Při vytváření anotačního typu není možné implementovat žádné rozhraní ani dědit od jiného anotačního typu nebo čehokoliv jiného. Každý anotační typ je automaticky potomkem třídy java.lang.annotation.Annotation. I tento vztah dědění bude do grafu zaznamenán klasickým způsobem, jaký je u rozhraní.

Modifikátory anotačního typu jsou stejné jako u rozhraní a proto budou ukládány stejným způsobem.

Gramatika těla anotačního typu je v dokumentaci Java popsána následovně:
AnnotationTypeElementDeclaration:
    AbstractMethodModifiersopt Type Identifier ( ) Dimsopt DefaultValueopt ;
    ConstantDeclaration
    ClassDeclaration
    InterfaceDeclaration
    EnumDeclaration
    AnnotationTypeDeclaration
    ;

DefaultValue:
    default ElementValue
Zde jsou opětjisté podobnosti s deklarací rozhraní resp. třídy. Deklarace konstant, vnitřních tříd a rozhraní je stejná jako v deklaraci rozhraní. Rozdíl jde vidět u deklarace metod. V deklaraci anotačního typu nelze deklarovat generickou metodu a dále zde lze nastavit defaultní hodnotu metody. Protože nás defaultní hodnota metody nezajímá budeme tuto informaci v grafu ignorovat. S takovýmto zjednodušením lze na deklaraci abstraktních metod v anotačním typu pohlížet stejně jako na deklaraci metod v klasickém rozhraní. Tělo deklarace anotačního typu navíc umožňuje deklaraci výčtů (enum) a další vnitřní anotační typy. S deklarovanými vnitřními výčty a anotačními typy bude pracováno jako s klasickými vnitřními třídami. Bude vytvořen vztah s názvem have_inner mezi vrcholem anotačního typu a relevantním vrcholem (vrcholem výčtu nebo vnitřním anotačním typem).

Souhrn

Vlastnosti:
  • name (String)
  • static (yes/no)
  • abstract (yes/no)
  • inner (yes/no)
  • access (public/private/protected)
  • package (String) 
  • strictfp (yes/no) 
Vztahy:
  • extends (java.lang.annotation.Annotation)
  • uses (Třída, výčet nebo rozhraní)
  • have_inner (Vnitřní třída, výčet nebo rozhraní)
  • have_anonym (Anonymní třída)
  • have_method (Metoda)
  • have_attribute (Atribut)
Jednoduchým příkladem může být následující kód a jeho odpovídající graf. V příkladu je deklarováno vnitřní rozhraní s atributem. Dále jeden atribut s datovým typem String a jedna metoda s návratovým typem int (lze použít pouze primitivních datových typů, čili datový typ void není povolen) a defaultní hodnotou.


1
2
3
4
5
6
7
8
9
package test_package;
public @interface AnotType {
 interface VnitrniRozhrani{
  public static String jina_konstanta = "hodnota";
 };
 public VnitrniRozhrani vr = new VnitrniRozhrani() {};
 public String konstanta = "hodnota";
 public int metoda () default 1;
}



Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.6

Uložení rozhraní jako grafu

Dokumentace Java definuje rozhraní jako nový referenční typ, který může obsahovat třídy, rozhraní, konstanty a abstraktní metody. Rozhraní neobsahuje implementaci metod, avšak implementující třídy musí tyto metody implementovat.
InterfaceDeclaration:
    NormalInterfaceDeclaration
    AnnotationTypeDeclaration

NormalInterfaceDeclaration:
    InterfaceModifiersopt interface Identifier
    TypeParametersopt ExtendsInterfacesopt InterfaceBody
Máme k dispozici 2 druhy deklarací rozhraní. Buď deklarujeme klasické rozhraní, nebo anotační typ. Deklaraci anotačních typů se věnuje další článek.

Hlavička klasického rozhraní obsahuje Seznam modifikátorů, klíčové slovo pro identifikaci deklaracec rozhraní, identifikátor označující konkrétní rozhraní. Dále je možné přiložit typové parametry, pokud deklarujeme generické rozhraní. Následně máme možnost vypsat seznam rozhraní, od kterých chceme dědit. Nakonec je nutno napsat tělo rozhraní.

Možné modifikátory při deklaraci rozhraní jsou:
  • Annotations
  • public
  • protected
  • private
  • abstract
  • static
  • strictfp
Rozhraní má také možnost být oanotováno. Toto značí modifikátor Annotations a v grafu bude anotace rozhraní interpretována vztahem s názvem have_annotation, který bude mezi vrcholem rozhraní a anotací. Modifikátory přístupu budou také zaznamenány do vlastnosti s názvem access a ostatní modifikátory budou mít vlastní vlastnost se stejnojmenným názvem a pravdivostní hodnotou.

Dědění od jiných rozhraníbude značeno vztahem s názvem extends, který bude mezi vrcholem dědícího rozhraní a rozhraní, od kterého je děděno.Na rozdíl od tříd, je možné dedit od více rozhraní.

Jak již bylo řečeno, v těle deklarace rozhraní mohou být:
  • deklarace konstant
  • deklarace abstraktních metod
  • deklarace tříd
  • deklarace dalších rozhraní
Pokud porovnáme možný obsah třídy a rozhraní, z hlediska uložení do grafumůžeme najít podobnosti. Například deklarace tříd a rozhraní může být obsaženo jak ve třídě, tak v rozhraní. V grafu tak budou tyto entity uloženy jako vrchol s patřičným typem a bude navázán vztah mezi rozhraním a touto členskou entitou s názvem have_inner. Dále je ve třídě umožněno deklarovat metody, ale v rozhraní je možné deklarovat pouze abstraktní metody. Abstraktní metody jsou však podmnožina klasických metod, takže je možné s nimi pracovat a ukládat je stejným způsobem, čili pro metodu bude vytvořen zvláštní vrchol s typem metoda a vytvoří se vztah mezi rozhraním a touto metodou. Podobná situace nastává u konstant v rozhraní a atributů ve třídě. Pro každou konstantu v rozhraní bude vytvořen vrchol s typem atribut a vztahem se vytvoří relace mezi rozhraním a tímto atributem zastupujícím konstantu.

Souhrn

Vlastnosti:
  • name (String)
  • static (yes/no)
  • abstract (yes/no)
  • inner (yes/no)
  • access (public/private/protected)
  • package (String) 
  • strictfp (yes/no) 
Vztahy:
  • extends (Rozhraní)
  • uses (Třída, rozhraní nebo výčet)
  • have_inner (Vnitřní třída, rozhraní nebo výčet)
  • have_anonym (Anonymní třída)
  • have_method (Metoda)
  • have_attribute (Atribut)
Jako jednoduchý příklad vytvoříme rozhraní s jednou abstraktní metodou a dvěmi konstantami, z nichž jedna je instancí vnitřního rozhraní.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
public interface Rozhrani extends Runnable{

 interface VnitrniRozhrani{
  public static String jina_konstanta = "hodnota";
 };

 public static String konstanta = "hodnota";
 public VnitrniRozhrani vr = new VnitrniRozhrani() {};
 public void metoda();
}



Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.1

pátek 3. dubna 2015

Uložení atributu třídy jako grafu

Gramatika jazyka Java specifikuje deklaraci atributů třídy následujícím popisem.
FieldDeclaration:
    FieldModifiersopt Type VariableDeclarators ;
 Akceptovatelné modifikátory pro atributy jsou:
  • Annotation
  • public
  • protected
  • private
  • static
  • final
  • transient
  • volatile
Annotation značí anotaci atributu a bude v grafu zaznačena vztahem have_annotation podobně jako je tomu u metod nebo tříd. Přístupové modifikátory public, protected a private budou opět zaznamenány ve vlastnosti access. Všechny ostatní modifikátory, tedy static, final, transient a volatile, budou v grafu interpretovány vlastní vlastností se stejnojmenným názvem a pravdivostní hodnotou.

Další část deklarace Type specifikuje datový typ atributu. Podobně, jako je tomu u návratových hodnot metod a datového typu parametrů metod, bude tato vlastnost charakterizována vztahem s názvem is_type, který bude mezi vrcholem atributu a referencovaným typem. Jetliže bude datový typ atributu generický, tedy že datový typ atributu bude znám až po instanciaci, bude vztah značící datový typ  navázán na speciální vrchol pro typové parametry.

Poslední částí je určení názvu atributu, který může obsahovat buď pouze název atributu, název s označením atributu jako pole (označí se hranatými závorkami), nebo inicializaci atributu. Název se ukládá do vlastnosti name. Jestliže se však jedná o pole, není vrchol atributu spojen čistě s vrcholem datového typu ve vztahu is_type. Potom se mezi těmito vrcholy nacházi další vrchol typu pole, který značí, že se jedná o pole. V tomto vrcholu se uchovává pouze jediná věc a to, jakého datového typu je. Tento vztah je pojmenován main_type.

Shrnutí pole

Vlastnosti:
Vztahy:
  • main_type (Třída)

Shrnutí atributu

Vlasnosti:

  • name (String)
  • static (yes/no)
  • final (yes/no)
  • access (public/private/protected)
  • transient (yes/no)
  • volatile (yes/no)
Vztahy:
  • have_annotation (Anotace)
  • is_type (Třída)
Nyní si ukážeme jednoduchý příklad uložení atributů třídy do grafu. Následuje zdrojový kód v jazyce Java, který deklaruje několik atributů a poté je vyobrazen relevantní graf.


1
2
3
4
public class Trida{
 public static String pole[];
 private transient int pocet;
}




Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3

úterý 31. března 2015

Uložení metody jako grafu

Dle specifikace jazyka Java metody deklarují spustitelný kód, který můžeme volat. Metody mohou být parametrizovány.

Popis deklarace metody je následující
MethodDeclaration:
    MethodHeader MethodBody
MethodHeader:
    MethodModifiersopt TypeParametersopt Result MethodDeclarator Throwsopt
MethodDeclarator:
    Identifier ( FormalParameterListopt )
Z popisu je zjevné, že metoda se skládá z hlavičky a těla metody. Hlavička může obsahovat seznam modifikátorů, parametrický typ a referenci na třídu zajišťující zachytávání vjímek. Nutný obsah hlavičky metody je návratový typ a název s případným seznamem přijímaných parametů.

Jako modifikátor metody lze použít:
  • Annotation
  • public
  • private
  • protected
  • abstract
  • static
  • final
  • synchronized
  • native
  • strictfp
První modifikátor značí anotaci metody. Nejedná se o řetězec "Annotation" nýbrž, že může před metodou být anotace, která se k této metodě vztahuje. Tato anotace bude v grafu interpretována vztahem metody s vrcholem anotace s názvem have_annotation. Modifikátory public, private a protected jsou grafem zachyceny vlastností vrcholu metody s názvem access. Dále bude mít vrchol grafu s typem metoda vlastnosti abstract, static, final, synchronized, strictfp a native značící stejnojmenné modifikátory metody.

Generickým metodám lze parametrizovat datový typ parametru, návratové hodnoty anebo třídy zajišťující zpracování vyjímek. Typové parametry se při deklaraci metody zadávají do špičatých závorek např.: <T>. Udávají tak název typového parametru v metodě. V extrémním případě může deklarace metody vypadat následovně:

1
2
3
public <T extends Exception> T method(T prom) throws T{
 return prom;
}

V grafu bude každý generický element (typ návratové hodnoty, datový typ parametru, třída pro zpracování vyjímek) navázán vztahem určujícím datový typ na speciální uzel značící typový parametr. 

Hlavička metody může obsahovat throws klauzuli pro deklaraci tříd zajišťujících zpracovávání vyjímek. Každá metoda může takto deklarovat žádnou nebo více tříd. Tato vlastnost bude v grafu zaznamenána vztahem throws mezi současnou třídou a referencovanou třídou.

Každá metody má svůj návratový datový typ. Ten může být buď void nebo jiný datový typ. Tato vlastnost bude zachycena vztahem s názvem is_type mezi metodou a referencovaným typem (resp. třídou). Dále bude mít vrchol metody vztah have_parameter se všemi svými parametry. Popis vrcholu parametru je níže.

Je popsáno ukládání hlavičky metody do grafu. Nyní je potřeba extrahovat některé informace z těla metody. Tělo metody obsahuje blok kódu. Z tohoto bloku kódu nás zejména zajímají metody volané z těla, metody volané příkazem throw, třídy využívané v klauzuli catch a používané datové typy. Abychom zachytili všechny metodou používané datové typy, označíme všechny datové typy proměnných v těle metody, parametry a návratové typy jako používané a vytvoří se vztah mezi metodou a referencovanou třídou s názvem uses. Jestliže se v těle metody najde volání jiné metody, vytvoří se vztah mezi metodou, odkud je volána metoda a volanou metodou s názvem call. Dále pokud metoda používá jinou třídu (datový typ) anebo volá metodu nějaké třídy, vytvoří se vztah uses mezi třídou, ve které je metoda deklarována a třídou, která je používaná nebo je je volána některá její metoda. Jestliže se nalezne klauzule throw v bloku kódu, bude vytvořen vztah s názvem call_throw s vrcholem metody, jež odpovídá referenci. Stejným způsobem se naváže vztah uses mezi analyzovanou třídou a třídou deklarující volanou metodu. Poslední požadovaná informace z těla kódu jsou datové typy zachytávaných vyjímek klauzulí catch. Pokud se tedy na nějaký takový datový typ narazí, vytvoří se vztah s názvem catch s patříčnou třídou.

Souhrn

Vlastnosti:
  • name (String)
  • static (yes/no)
  • final (yes/no)
  • access (public/private/protected)
  • abstract (yes/no)
  • synchronized (yes/no) 
  • native (yes/no)
  • strictfp (yes/no) 
Vztahy:
  • is_type (Třída)
  • have_parameters (Parametr)
  • call (Metoda)
  • uses (Třída)
  • throws (Třída) 
  • have_annotation (Anotace) 
  • call_throw (Metoda)
  • catch (Třída)
Totožný popis uložení do grafu platí také pro konstruktory metody. Jediný rozdíl v tomto případě je v typu vrcholu.

Parametry

Deklarace metody obsahuje také deklarace parametrů metody. Parametr může následovat po anotaci. Což se v grafu znázorní vztahem parametru s vrcholem anotace s názvem have_annotation. Dále mohou být určeny modifikátory, které však umožňují pouze řetězec final. Tento modifikátor bude tedy zařazen mezi možné vlastnosti vrcholu v grafu. Nutnou součástí je určení datového typu parametru a název parametru. V grafu bude název parametru zařazen mezi vlastnosti vrcholu a typ parametru bude interpretován hranou mezi uzlem parametru a referencovaným typem.

V jazyce Java je možné při deklaraci metody nastavit poslední parametr jako proměnlivý (variable arity parameter). Toto umožuje vložit do parametru libovolný počet parametrů deklarovaného typu. Popis této kontrukce je následující:
VariableModifiersopt Type... VariableDeclaratorId
Tedy je možné jej rozeznat pomocí třech teček mezi určením typu a názvu parametru. Toto se však může vyskytkou pouze jako poslední parametr. Proměnliné parametry budou v grafu zaznamenány jako pole odpovídajícího datového typu. Tedy pokud bude parametr deklarován podle následující ukázky, bude mít metoda jeden parametr s názvem prom, který bude mít vztah s vrcholem pole a to bude mít vztah s vrcholem String.

metoda(String...prom){}

V grafu bude parametr interpretován jako zvláštní vrchol. Podle možných modifikátorů a dalších možných vlastností parametru bude do seznamu vlastností vrcholu ukládáno dle následujícího souhrnu. Navíc se bude ukládat pozice parametru mezi ostatními parametry, protože při porovnávání reference metod je důležitý počet parametrů a posloupnost datových typů.

Souhrn pro parametr

Vlastnosti:
  • name (String)
  • final (yes/no)
  • position (int)
 
Vztahy:
  • is_type (Třída)
  • have_annotation (Anotace)

Jako komplexní příklad uložení metody a jeho parametrů do grafu nám poslouží následující kód.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package test_package;

import java.io.IOException;

public class test_metoda <T> {

 public synchronized strictfp String metoda(T par) throws Exception{
  
  double d;
  if (par instanceof String){
   
  }else{
   throw new Exception();
  }
  
  try{
   d = 3/0;
  }catch(Exception e){
   // ...
  }
  
  
  return "";
 }
}



Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4

středa 25. března 2015

Uložení třídy jako grafu

Podle popisu třídy v dokumentaci Java7 (docs.oracle.com) deklarace třídy definuje nový referenční typ a popisuje, jak je implementována.

Existují třídy tzv. top level a naopak vnořené třídy. Vnořené třídy jsou deklarované uvnitř jiné třídy nebo rozhraní. Mezi vnořené třídy se řadí členské třídy, lokální třídy a anonymní třídy. V grafu budou mít vnitřní třídy speciální vrchol, kde anonymní třídy budou odlišeny jiným druhem vrcholu.

Třída může obsahovat atributy, metody, instance, statickou inicializaci a konstruktory. V grafu budou mít třídy vztah s atributy (have_attribute) a metodami (have_method). S konstruktory bude zacházeno jako s metodami s tím rozdílem, že budou vrcholy odlišeny typem.

Popis deklarace třídy je následující:
ClassDeclaration:
    NormalClassDeclaration
    EnumDeclaration

NormalClassDeclaration:
    ClassModifiersopt class Identifier TypeParametersopt
                                               Superopt Interfacesopt ClassBody
Z první části je zjevné, že existují dva druhy tříd. První jsou normální třídy a druhou je výčet (enum). Mezi normální třídou a výčtem je mnoho rozdílného, z hlediska grafu však ne, proto budou tyto dvě entity rozlišeny pouze typem vrcholu a dále s nimi bude zacházeno stejně.

Při deklaraci třídy jsou možné následující modifikátory:
  • Annotation
  • public
  • protected
  • private
  • abstract
  • static
  • final
  • strictfp  
Modifikátor Annotation značí anotaci třídy. Tedy, že v tomto místě bude anotace, která se vztahuje na následující třídu. Tento vztah bude symbolizován hranou mezi třídou a vrcholem anotace s názvem have_annotation. Přístupové modifikátory public, protected a private budou zachyceny v grafu vlastností access. Abstract, static a final mají v grafu speciální položku mezi vlastnostmi vrcholu. Strictfp, který striktně vynucuje plovoucí řadovou čárku u výrazů (2) bude do grafu ukládán pod stejným názvem.

S třídami, které deklarují generický typ bude zacházeno jako s ostatními třídami. Jméno třídy bude použito bez typového parametru. Java kompilátor se již postará o to aby byl typový parametr používán správně, proto není potřeba toto v grafu ošetřovat.

Třída může dědit od rodiče, kterého může mít pouze jednoho. V grafu nebude na počet předků brán zřetel (o to se stará kompilátor). Vrchol zastupující třídu tak bude mít možnost mít vztah s jinou třídou (extends), což bude charakterizovat dědění. Dále může třída implementovat rozhraní. Je možné implementovat více rozhraní, proto v grafu bude možnost navázat vztah na více vrcholů typu rozhraní.

Protože z hlediska vytváření grafu není mezi vnitřní třídou, anonymní třídou a jinou třídou rozdíl, bude s nimi pracováno stejně. Budou však rozlišeny typem vrcholu.

Protože není potřeba podrobně mapovat strukturu java balíků (package), bude tato informace uložena v každé tříde pouze jako vlastnost.


Souhrn

Vlastnosti:
  • name (String) 
  • static (yes/no)
  • abstract (yes/no)
  • final (yes/no)
  • anonym (yes/no)
  • inner (yes/no)
  • access (public/private/protected)
  • package (String) 
  • strictfp (yes/no) 
Vztahy:
  • extends (Třída)
  • uses (Třída)
  • implements (Rozhraní)
  • have_inner (Vnitřní třída)
  • have_anonym (Anonymní třída)
  • have_method (Metoda)
  • have_attribute (Atribut)
  • have_annotation (Anotace)
Stejný popis vrcholu bude mít vnitřní třída, anonymní třída a výčet.

Pro příklad je vytvořen následující kód. Třída s názvem Třída je označena modifikátory public a final. Dále tato třída dědí od třídy Object a implementuje rozhraní s názvem Runnable. Toto rozhraní vyžaduje implementaci metody run. Třída dále obsahuje jeden atribut, který je navíc typu, jež je deklarován uvnitř třídy. Obsažena je tedy také vnitřní třída s názvem VnitrniTrida, která disponuje jením atributem.

Ukážeme si, jak by mohl vypadat graf pro tento kód.



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package experiment;

public final class Trida extends Object implements Runnable{
    class VnitrniTrida{
        public String atribut_vnitrni_tridy;
    }

    private VnitrniTrida atribut = new VnitrniTrida();
    public void run() {
        // ..
    }
}




Zdroje:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.4