LogTalk_UMLgraph

Generowanie diagramów klas UML w języku Prolog

Zrealizował: Mariusz Sasko (4RI)

Cele Projektu:

  • Analyze, describe, prepare a short tutorial as S5 for UMLgraph.
  • Provide a simple Prolog API for genarating, and visualizing UML diagrams from Prolog, write a Prolog parser
  • Research on existing approaches to representing UML in/with Prolog
  • Analyze, describe, prepare a short tutorial as S5 for LogTalk.
  • Check first has anyone made some progress in the integration of these two!
  • Provide menas for generating visualizations of UML diagrams from Prolog for LogTalk

Podstawy UMLGraph.

  • UMLgraph został napisany przez greckiego profesora uniwersytetu Ateńskiego o imieniu Diomidis Spinellis.
  • Pierwsze publiczne wydanie UMLgraph to wersja 1.15 wydana w 2002-07-26. Od tej pory projekt przeszedł różne modyfikacje i zostały dodane nowe funkcjonalności. Aktualna wersja 5.2 została wydana 2008-12-03, a obecnie trwają prace nad wersją 5.3.
  • UMLgraph jest wydawany na bardzo liberalnej licencji BSD(Berkeley Software Distribution License), której podstawą jest wolny dostęp do kodu źródłowego, możliwość jego modyfikacji i ulepszania, a także rozprowadzanie programu w nowej zmodyfikowanej postaci, po to aby mogła korzystać z nich cała społeczność.

Instalacja i wymagania UMLGraph!

Musimy najpierw posiadać następujące pakiety w systemie:

  • Java Jdk 6
  • GraphViz

Aby korzystać z UMLGraph należy odpowiednio zmodyfikować skrypt: /ścieżka/UMLGraph/bin/umlgraph

Cechy UMLGraph.

  • Jak sama nazwa wskazuje UMLgraph jest narzędziem umożliwiającym rysowanie diagramów UML (Unified Modeling Language), służących do modelowania obiektów w analizie obiektowej. Opis diagramu UML jest czysto tekstowym opisem reprezentacji, który UMLgraph analizuje i przedstawia w odpowiedniej formie graficznej.
  • Narzędzie stworzone specjalnie dla języka Java. UMLgraph potrafi analizować składnię i semantykę tego języka i na podstawie analizy tworzyć diagramy UML.
  • Nie wymaga on pełnych definicji metod czy nawet klas. Definiujemy to co chcemy aby znalazło się na diagramie.
  • Pozwala on między innymi na ingerowanie w to jak chcemy aby dany element był przedstawiony na diagramie za pomocą dodanych w komentarzach komend JavaDoc, przed definicją klasy, której mają dotyczyć.
  • UMLGraph generuje diagramy w formatach: gif, ps, png, svg.

UMLGraph pozwala modelować (1):

  • klasy (używając tagu: @opt shape nazwa )
  • funkcje (wyspecyfikowane jako metody w klasie)
  • atrybuty (wyspecyfikowane jako pola w klasie)
  • stereotypy (używając tagu: @stereotype nazwa )
  • wartości oznaczone (używając tagu: @tagvalue nazwa wartość )

UMLGraph pozwala modelować (2):

  • relację implementowania (używając deklaracji z języka Java: implements )
  • relację dziedziczenia (używając deklaracji z języka Java: extends albo tagu: @extends )
  • relację assocjacji (używając tagu: @assoc )
  • relację skierowanej assocjacji (używając tagu: @navassoc )
  • relację agregacji (używając tagu: @has )
  • relację kompozycji (używając tagu: @composed )
  • relację zależności (używając tagu: @depend )

Opcje:

  • @opt … - służy do formatowania. Posiada liczne opcje z którymi można go stosować. Dokładny opis wszystkich możliwości znajduje się pod linkiem: Tag @opt.
  • @note … - powoduje dodanie dodatkowej etykiety,
  • @view @match - są to znaczniki używane do nadania pewnych opcji klasom których nazwy spełniają np. wyrażenie regularne. Widoki są dziedziczone od innych klas i posiadają ich cechy.
  • @hidden - dany obiekt nie będzie przedstawiony na diagramie, służy do definiowania parametrów w całym pliku|

Przykład:

/**
 * @opt shape class
 * @opt edgecolor "yellow"
 * @opt nodefontname "Times"
 * @opt nodefillcolor "#a0a0a0"
 * @opt nodefontsize 14
 * @hidden
 */
class UMLOptions{}

/**
 * @opt nodefontname "Helvetica-Bold"
 * @opt nodefontcolor "white"
 * @note opis ...
 * ... kontynuacja opisu ...
 * @note inny opis ....
 */
class klasa{}

Przykład:

Ciekawe miejsca:

  • Pierwsza klasa nie jest pokazana na diagramie. Dzieje się to za sprawą znacznika @hidden.
  • klasa{} posiada cechy wyszczególnione dla UMLOptions{}. Jest to sposób na ustawianie wartości domyślnych dla wszystkich obiektów w pliku, a także elementów takie jak np. tło diagramu. Cechy zostają odziedziczone przez kolejne obiekty.

Początki języka LogTalk

  • Język napisany przez Paulo Moura.
  • Pierwsza wersja LogTalk 1.0 została wydana w 1995 roku.
  • W 1998 roku, przyszła na świat wersja 2.0, która do tej pory jest wersją aktualną i nie jest ona kompatybilna z LogTolk 1.0.
  • Najnowsza wersja 2.35.1 została wydana dosłownie przed kilkoma dniami, bo 1 marca 2009 roku.
  • Informacje dotyczące rozwoju tego projektu są systematycznie publikowane na stronie http://logtalk.org/news.html. Ponadto jest prowadzony blog o tym języku, gdzie można również szukać informacji dotyczących tego projektu: http://blog.logtalk.org.

Cechy LogTalk!

  • LogTalk jest rozszerzeniem dla języka Prolog, który wzbogaca go o dodatkowe możliwości.
  • LogTalk jest próbą integracji programowania logicznego z programowaniem obiektowym.
  • Pozwala na enkapsulowanie bazy wiedzy, napisanej w deklaratywny sposób, wewnątrz obiektu. Dzięki temu jest ona dostępna jedynie tam gdzie jest potrzebna, a kod programu staje się łatwiejszy w utrzymaniu i bardziej efektywny.
  • Od strony programisty definiowanie obiektu jest podobne do tworzenia kilku przestrzeni nazw z osobnymi bazami wiedzy w każdym obiekcie.

O jakie cechy LogTalk wzbogaca Prolog?

  • Integracja programowania logicznego z programowaniem obiektowym.
  • Wielokrotne używanie napisanego kodu.
  • Wsparcie zarówno dla programowania opartego na klasach jak i prototypach.
  • Utrzymywanie hierarchii obiektów.
  • Separacja interfejsów od definicji klas.
  • Możliwość ukrywania składników klas. Występują cztery typy praw dostępu do komponentów obiektu: pakietowy, private, protected, i public.
  • Dziedziczenie.
  • Wsparcie dla aplikacji wielowątkowych.
  • Polimorfizm. Wsparcie dla wczesnego jak i późnego wiązania.

Elementy języka.

  • obiekty - prototypy, klasy i instancje. Obiekty tworzymy za pomocą dyrektyw: object/1-5 oraz end_object/0, pomiędzy którymi umieszczamy definicję obiektu.
  • protokoły - odpowiedniki interfejsów. Definicje protokołów są enkapsulowane pomiędzy dwiema dyrektywami: protocol/1-2 i end_protocol/0.
  • kategorie - nie posiadają odpowiedników. Są to kontenery zawierające pewne funkcjonalności. Kategorie są tworzone dzięki dyrektywom category/1-3 oraz end_category/0.
  • predykaty - odpowiedniki funkcji.

Relacje między obiektami.

LogTalk pozwala na tworzenie obiektów, które nie są związane z innymi żadną relacją, jak i tworzyć hierarchie obiektów oparte na prototypach albo klasach. Można ponadto używać zarówno pojedynczego jak i wielokrotnego dziedziczenia.

  • objectName - nazwa obiektu, argument obowiązkowy.
  • implements(protocolName) - protokół implementowany przez dany obiekt.
  • imports(categoryName) - kategoria importowana przez dany obiekt.
  • extends(parentName) - rodzic po którym następuje dziedziczenie.
  • instantiates(className) - obiekt jest instancją klasy className.
  • specializes(superclassName) - obiekt jest podklasą a superclassName superklasą.

Deklarowanie Predykatów.

  • Wszystkie Predykaty do których chcemy mieć dostęp z innych obiektów muszą być zadeklarowane.
  • Deklaracja musi zawierać przynajmniej nazwę predykatu oraz liczbę argumentów.
  • Muszą one poprzedzać definicję albo wywołanie w celu zapewnienia poprawnego przebiegu kompilacji.

Zakres widoczności:

  • public - predykat można wołać z dowolnego obiektu.
  • protected - mogą być wołane jedynie z potomka lub w obiekcie w którym są zdefiniowane.
  • private - dostęp do predykatów ma jedynie obiekt w którym jest zdefiniowany.
  • local - jak predykaty prywatne mogą być jedynie wołane z obiektu, ale są niewidoczne dla mechanizmu obsługi błedów.

Przykład.

Predykaty dla obiektów w LogTalk są definiowane tak samo jak w Prologu. Dodawane są jedynie dodatkowe znaczniki.

:- object(list).
    :- public(append/3).
    :- public(member/2).
 
    append([], L, L).
    append([H| T], L, [H| T2]) :-
        append(T, L, T2).
 
    member(H, [H| _]).
    member(H, [_| T]) :-
        member(H, T).
:- end_object.

Uzyskiwanie informacji o obiektach.

  • | ?- instantiates_class(InstanceName, ClassName). - Sprawdza czy zachodzi relacja instantiates.
  • | ?- specializes_class(ClassName, SuperclassName). - Sprawdza czy zachodzi relacja specializes.
  • | ?- extends_object(ObjectName, ParentName). - Sprawdza czy zachodzi relacja extends.
  • | ?- imports_category(ObjectName, CategoryName). - Sprawdza czy zachodzi relacja imports.
  • | ?- implements_protocol(ObjectName, ProtocolName). - Sprawdza czy zachodzi relacja implements.
  • | ?- object_property(ObjectName, PropertyName). - Sprawdza czy ObjectName posiada właściwość PropertyName.

Uzyskiwanie informacji o protokołach.

  • | ?- extends_protocol(ProtocolName1, ProtocolName2). - Sprawdza czy zachodzi relacja extends.
  • | ?- implements_protocol(ObjectOrCategoryName, ProtocolName). - Sprawdza czy zachodzi relacja implements.
  • | ?- protocol_property(ProtocolName, PropertyName). - Sprawdza czy ProtocolName posiada właściwość PropertyName.

Uzyskiwanie informacji o kategoriach.

  • | ?- extends_category(CategoryName1, CategoryName2). - Sprawdza czy zachodzi relacja extends.
  • | ?- imports_category(ObjectName, CategoryName). - Sprawdza czy zachodzi relacja imports.
  • | ?- implements_category(ObjectName, CategoryName). - Sprawdza czy zachodzi relacja implements.
  • | ?- category_property(CategoryName, PropertyName). - Sprawdza czy CategoryName posiada właściwość PropertyName.

Instalacja i uruchamianie programów LogTalk.

  1. Odpowiednie pakiety w zależności od tego na jakim systemie operacyjnym pracujemy pobieramy ze strony: http://logtalk.org/download.html
  2. Uruchomienie LogTalk to po prostu uzgodnienie dwóch plików:
:-consult('/usr/share/logtalk/configs/swi').
:-consult('/usr/share/logtalk/compiler/logtalk').

Kompilowanie plików LogTalk:

logtalk_compile([source_file1, source_file2, ...]).
logtalk_load([source_file1, source_file2, ...]).

Zaproponowane rozwiązanie.

Obiekt javaobject - zawiera następujące publiczne predykaty:

  • object_drow/1 - zapisuje obiekty, za pomocą skłądni Java.
  • category_drow/1 - zapisuje kategorie, za pomocą skłądni Java.
  • predicate_drow/1 - zapisuje predykaty, za pomocą skłądni Java.

Obiekt javacomment - zawiera następujące publiczne predykaty:

  • setComment/1 - przyjmuje listę stringów. Stosuje się go do umieszczenia dodatkowych definicji opisującymi tworzone diagramy.
  • setAsUMLMainComment/0 - ustawia zasięg komentarza dla całego diagramu.

Zaproponowane rozwiązanie.

Obiekt javaobject - zawiera następujące publiczne predykaty:

  • object_drow/1 - zapisuje obiekty, za pomocą skłądni Java.
  • category_drow/1 - zapisuje kategorie, za pomocą skłądni Java.
  • predicate_drow/1 - zapisuje predykaty, za pomocą skłądni Java.

Obiekt javacomment - zawiera następujące publiczne predykaty:

  • setComment/1 - przyjmuje listę stringów. Stosuje się go do umieszczenia dodatkowych definicji opisującymi tworzone diagramy.
  • setAsUMLMainComment/0 - ustawia zasięg komentarza dla całego diagramu.

Zaproponowane rozwiązanie.

Obiekt mainobject - zawiera następujące publiczne predykaty:

  • mainFunction/0 - ten predykat należny zdefiniować samemu. Zawiera on definicję diagramu. Opisujemy tutaj elementy, które chcemy rysować na diagramie za pomocą javaobject, dodając komentarze opisujące diagram za pomocą javacomment.

Plik drow.pl:

  • drow/0 - predykat ładuje wybrany plik LogTalk i zapisuje go do pliku.

Obiekty w pliku drowobject.lgt.

  • plik służy do zademonstrowania przykładu działania prezentowanego rozwiązania.

Zaproponowane rozwiązanie.

Skrypt umlgraph gdzie:

  • ${1} oznacza nazwę kompilowanego pliku prologa.
  * ${2} oznacza nazwę wywoływanego predykatu.
  • ${3} oznacza format w jakim zostanie zapisany diagram.

Za pomocą poniższej komendy dostajemy plik .java i diagram drow.png

./umlgraph drow drow png

Diagram drow.png

Ograniczenia i problemy.

  • Ograniczenia UmlGraph - interpretuje tylko Javę
  • Problem z inną semantyką LogTalk i JAVA - brak kategorii w Javie
  • Brak typów w LogTalk - konieczność dodania sztucznych typów.
  • Brak możliwości dostępu do predykatów prywatnych - nie można ich pokazać na diagramie.

Materiały