{"id":21470155,"url":"https://github.com/gabri-viane/utils","last_synced_at":"2025-03-17T06:42:33.352Z","repository":{"id":194741374,"uuid":"356673684","full_name":"gabri-viane/Utils","owner":"gabri-viane","description":"Insieme di metodi e classi di gestione avanzate.","archived":false,"fork":false,"pushed_at":"2021-10-01T08:43:18.000Z","size":314,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-23T16:12:16.751Z","etag":null,"topics":["console-visualization","utils-lib","utils-library","xml-parser","xml-serializer"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gabri-viane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-04-10T19:19:52.000Z","updated_at":"2023-08-04T20:06:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"55cc4bbe-8a0b-4a3d-9694-2b645973d31d","html_url":"https://github.com/gabri-viane/Utils","commit_stats":null,"previous_names":["gabri-viane/utils"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabri-viane%2FUtils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabri-viane%2FUtils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabri-viane%2FUtils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabri-viane%2FUtils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gabri-viane","download_url":"https://codeload.github.com/gabri-viane/Utils/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243988956,"owners_count":20379649,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console-visualization","utils-lib","utils-library","xml-parser","xml-serializer"],"created_at":"2024-11-23T09:24:04.232Z","updated_at":"2025-03-17T06:42:33.332Z","avatar_url":"https://github.com/gabri-viane.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Indice\n0. [Libreria Utils](#libreria-utils)\n\t1. [Generalità](#generalità)\n1. [Console](#1-console)\n\t1. [Input](#11-input)\n\t\t* [ConsoleInput](#consoleinput)\n\t\t* [Spiegazione metodi](#spiegazione-metodi)\n\t\t* [Esempio utilizzo](#esempio-utilizzo)\n\t\t* [ObjectInputEngine](#objectinputengine)\n\t\t\t* [Regole di utilizzo](#regole-di-utilizzo)\n\t\t\t* [Esempio utilizzo](#esempio-utilizzo-1)\n\t2. [Output](#12-output)\n\t\t* [GeneralFormatter](#generalformatter)\n\t\t\t* [Esempio utilizzo](#esempio-utilizzo-2)\n\t\t* [ObjectOutputEngine](#objectoutputengine)\n\t\t\t* [Esempio classi](#esempio-classi)\n\t\t\t* [Metodi di formattazione](#metodi-di-formattazione)\n\t3. [Menu](#13-menu)\n\t\t* [Istanziare nuovo menù](#istanziare-nuovo-menù)\n\t\t* [Rimuovere opzione](#rimuovere-opzione)\n\t\t* [Trovare indice opzione](#trovare-indice-opzione)\n\t\t* [Cambiare voce opzione](#cambiare-voce-opzione)\n\t\t* [Aggiungere opzioni](#aggiungere-opzioni)\n\t\t* [Azioni future (Eseguibili futuri)](#azioni-future-eseguibili-futuri)\n\t\t* [Reset del menù](#reset-del-menù)\n\t\t* [Eseguire il menù](#eseguire-il-menù)\n\t\t* [Funzionalità aggiuntive](#funzionalità-aggiuntive)\n\t\t* [Chiarimenti](#chiarimenti)\n2. [Grafi](#2-grafi)\n3. [Registro](#3-registro)\n4. [XML](#4-xml)\n\t1. [Elementi XML](#elementi-xml)\n\t\t* [Metodi XMLElement](#metodi-xmlelement)\n\t2. [Lettura e scrittura XML](#lettura-e-scrittura-xml)\n\t\t* [Scrittura](#scrittura)\n\t\t* [Lettura](#lettura)\n\t3. [XMLEngine](#xmlengine)\n\t\t* [Perchè conviene utilizzare delle classi personalizzate?](#perchè-conviene-utilizzare-delle-classi-personalizzate)\n\t\t* [Tags collegate a variabili di classe](#tags-collegate-a-variabili-di-classe)\n\t\t* [Tags collegate a metodi di classe e metodi di calcolo](#tags-collegate-a-metodi-di-classe-e-metodi-di-calcolo)\n\t4. [Strutture di controllo](#strutture-di-controllo)\n\t\t* [Modulo di struttura](#modulo-di-struttura)\n\t\t* [Controllo struttura](#controllo-struttura)\n\n# Libreria Utils\nAggiunge diverse classi di utilità base.\nSono presenti 4 *main-packages* (funzionalità distinte) nella libreria:\n1. Gestione dinamica della **console**;\n2. Implementazione dei **grafi** (Alberi e grafi generici);\n3. Dichiarazione di due **registri** (per ID e UUID);\n4. Gestione generalizzata di file **XML**.\n\nVerranno mostrate ogni sezione singolarmente per spiegarne l'utilizzo.\n\n------------\n## Generalità\n\nTutte le classi e tipi che **finiscono** con la parola `Engine` permettono di eseguire tramite *reflection* in modo totalmente dinamico e avanzato la gestione dei dati, vengono chiamati per semplicità \"motori di ...\".\nA loro volta tutte le classi e tipi che **iniziano** con `Engine` sono elementi utilizzati dai motori per gestire tramite *reflection* i dati.\n\n------------\n\n### 1. Console\nIl pacchetto `ttt.utils.console` contiene tutte le classi che permettono una gestione avanzata di input e output di oggetti e variabile tramite console.\n\nPacchetti:\u003cbr\u003e\n1.1 `input`: contiene tutte le classi e tipi necessari per la gestione avanzata di input.\u003cbr\u003e\n1.2 `output`:  contiene tutte le classi e tipi necessari per la formattazione e la gestione dell'output.\u003cbr\u003e\n1.3 `menu`: contiene due classi e un'interfaccia, si occupa della creazione di menù da stampare in console.\u003cbr\u003e\n\n#### 1.1 Input:\nContiene due classi di utilizzo principale: `ConsoleInput` e `ObjectInputEngine`.\n##### ConsoleInput\nLa classe *ConsoleInput* è una classe non instanziabile, che mette a disposizione il metodo statico `ConsoleInput.getInstance()` per ritornare l'unica istanza.\nQuesta classe mette a disposizione i metodi per leggere dalla console i seguenti tipi:\n- Integer\n- Long\n- Double\n- Float\n- Boolean\n- Character\n- String\n\nPer ogni tipo leggibile (tranne per i boolean in cui viene solamente posta una domanda del tipo sì\\no) vengono messi a disposizione 3 metodi in overload. Si porta l'esempio per la lettura degli interi:\n```java\n   /**\n     * Metodo 1\n     */\n    public int readInteger(String question){...}\n\n    /**\n     * Metodo 2\n     */\n    public Optional\u003cInteger\u003e readInteger(String question, boolean skippable, String skippable_keyword) {...}\n\n    /**\n     * Metodo 3\n     */\n    public Optional\u003cInteger\u003e readInteger(String question, boolean skippable, String skippable_keyword, Validator\u003cInteger\u003e v) {...}\n\n```\n###### Spiegazione metodi\n- Il metodo della *tipologia 1* chiede come parametro **solamente la domanda** da stampare in console per poi chiedere il valore in input.\u003cbr\u003e\n- Il metodo di *tipologia 2* chiede come parametri sempre la domanda, inoltre se il parametro `skippable = true` allora all'utente è **concesso di uscire dall'immissione** dal dato tramite una parola-chiave passata come stringa nel parametro `skippable_keyword`. Il metodo ritorna un `Optional\u003cObject\u003e` poiché nel caso si permette all'utente di non inserire nessun valore allora l'oggetto restituito sarà `null`.\n- Il metodo di *tipologia 3* rispetta tutte le condizioni della *tipologia 2* inoltre permette di validare l'input inserito dall'utente tramite l'interfaccia funzionale `Validator\u003cT\u003e` che mette a disposizione il metodo *validate* che scatena l'eccezione in caso di input invalido:\n```java\npublic void validate(T value) throws IllegalArgumentException;\n```\n###### Esempio utilizzo\nUn'esempio completo di utilizzo può essere fatto utilizzando il metodo di terza tipologia:\n```java\nConsoleInput ci = ConsoleInput.getInstance();\nOptional\u003cInteger\u003e valore_letto = ci.readInteger(\"Inserisci valore intero:\", true, \"esci!\", new Validator\u003cInteger\u003e(){\n\t@Override\n\tpublic void validate(Integer value) throws IllegalArgumentException{\n\t\tif(value\u003c0){\n\t\t\tthrow new IllegalArgumentException(\"sono ammessi solo valori positivi\");\n\t\t}\n\t}\n});\n```\nCon queste istruzioni si chiede all' utente la domanda \"Inserisci valore intero:\" e gli si permette di ignorare l'inserimento inserendo la parola-chiave \"esci!\". Inoltre il valore viene validato e risulta corretto solo se maggiore di 0.\n##### ObjectInputEngine\nLa classe *ObjectInputEngine* permette di \"estendere\" le funzionalità della classe *ConsoleInput* gestendo l'input completo di oggetti tramite console. Per usufruire correttamente di questa classe bisogna implementare correttamente anche le interfacce e annotazioni: `InputObject` (interfaccia), `InputElement` e `Order` (annotazioni).\nLa classe *ObjectInputEngine* non è istanziabile e mette a disposizione un solo metodo che gestisce l'input di oggetti:\n```java\npublic static \u003cT extends InputObject\u003e T readNewObject(Class\u003cT\u003e object, String nome_elemento)\n```\n###### Regole di utilizzo\nIl funzionamento è relativamente semplice: si passano come parametri la classe dell'oggetto che si vuole chiedere in input tramite la console e il nome dell'oggetto che verrà chiesto all'utente.\u003cbr\u003e\nL'oggetto che si vuole chiedere in input deve avere una classe che rispetti delle regole fondamentali, altrimenti l'input non verrà eseguito:\n1. La classe deve implementare l'interfaccia `ttt.utils.console.input.interfaces.InputObject`;\n2. La classe deve mettere a disposizione i metodi o attributi annotandoli con l'annotazione `ttt.utils.console.input.annotations.InputElement` e nel caso si volessero chiedere i valori in modo ordinato bisogna anche annotarli con `ttt.utils.console.input.annotations.Order`;\n3. **La classe deve avere un costruttore che non chiede parametri**;\n4. I metodi messi a disposizione devono avere un solo parametro che deve essere tra i tipi primitivi (e le loro classi di boxing) oppure classi che implementano *InputObject*.\n\n###### Esempio utilizzo\nSegue un esempio di completo di come usare correttamente le classi e metodi:\n```java\npublic class EsempioInput implements InputObject {\n\n    private Esempio2 valore;\n    private int valore1;\n\n    public EsempioInput() {\n    }\n\n    public Esempio2 getValore() {\n        return valore;\n    }\n\n\t//Dopo aver chiamato il metodo \"setValore1\" viene chiamato questo metodo\n\t//Dato che Esempio2 implementa l'interfaccia InputObject a sua volta viene chiamato il metodo di inserimento per quest'oggetto\n    @Order(Priority = 1)\n    @InputElement(Name = \"esempio2\", Type = Esempio2.class)\n    public void setValore(Esempio2 valore) {\n        this.valore = valore;\n    }\n\t//Viene chiamato per primo questo metodo (Priority=0 ha precedenza su tutti quelli con valore maggiore di 0)\n    @Order(Priority = 0)\n    @InputElement(Name = \"ID\", Type = Integer.class)\n    public void setValore1(Integer valore1) {\n        this.valore1 = valore1;\n    }\n}\n```\n```java\npublic class Esempio2 implements InputObject {\n\n    private String valore2;\n\n    public Esempio2() {\n    }\n//Il valore passato a Name è ciò che viene stampato alla richiesta del valore\n//La classe passata a Type è il tipo chi viene richiesto in input all'utente\n    @InputElement(Name = \"valore 2 in Esempio2\", Type = String.class)\n    public void setValore2(String valore2) {\n        this.valore2 = valore2;\n    }\n}\n```\nDefinite le due classi e impostati i metodi (e/o le variabili) che richiedono i valori si può fare la chiamata al motore di completamento:\n```java\n EsempioInput oggetto_letto = ObjectInputEngine.readNewObject(EsempioInput.class, \"crea esempio input\");\n```\n#### 1.2 Output:\nContiene due classi di utilizzo principale: `GeneralFormatter` e `ObjectOutputEngine`.\n\n##### GeneralFormatter\nLa classe *GeneralFormatter* è una classe non instanziabile, che mette a disposizione 4 metodi statici che aiutano a mantenere una coerenza nella stampa in console.\n\n```java\npublic static void printOut(String message, boolean newline, boolean error)\n```\nQuesto metodo chiede 3 parametri: il messaggio da stampare in console (*message*), se bisogna tornare a capo (*newline*) ed infine se è un messaggio di errore (*error*). Quando il testo viene stampato vengono inserite prima le indentazioni e poi stampato il testo. Per incrementare o decrementare le indentazioni si usano rispettivamente i metodi *incrementIndents* o *decrementIndents*.\u003cbr\u003e\nAll'inizio dell'esecuzione del programma non vengono stampate indentazioni (non sono ancora state aggiunte) perciò la funzione funziona allo stesso modo di `System.out.print()` se `newline = false`, mentre `System.out.println()` se `System.out.print()`. Allo stesso modo cambiando il parametro *error* si decide se stampare sullo stream di output, perciò se `error = true` viene usato `System.err` altrimenti `System.out`.\nNel caso si volesse stampare sulla stessa riga nella console dopo aver chiamato il metodo *printOut* con il parametro `newline = false` si deve usare il normale metodo `System.out.print()` altrimenti vengono inserite le indentazioni.\n###### Esempio utilizzo\nAd esempio:\n```java\n  printOut(\"testo1\",true,false);\n  incrementIndents();\n  printOut(\"testo2\",true,false);\n  decrementIndents();\n  printOut(\"testo3\",true,false);\n```\nStamperà:\n\u003etesto1\u003cbr\u003e\n\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;testo2\u003cbr\u003e\n\u003etesto3\n\nMentre non tornare a capo potrebbe causare il seguente comportamento non desiderato:\n```java\n  printOut(\"testo1\",false,false); //notare che non si torna a capo\n  incrementIndents();\n  printOut(\"testo2\",true,false);\n  decrementIndents();\n  printOut(\"testo3\",true,false);\n```\nStamperà invece:\n\u003etesto1\n\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;testo2\u003cbr\u003e\n\u003etesto3\n\nPer evitare questo comportamento bisogna scrivere:\n```java\n  printOut(\"testo1\",false,false); //notare che non si torna a capo\n  incrementIndents();\n  System.out.println(\"testo2\");\n  decrementIndents();\n  printOut(\"testo3\",true,false);\n```\nChe stamperà correttamente il contenuto voluto su una singola riga.\n\u003etesto1testo2\u003cbr\u003e\n\u003etesto3\n\n```java\npublic static void incrementIndents()\n```\nPermette di incrementare le indentazioni stampate in output prima di un testo passato al metodo *GeneralFormatter.printOut(...)*\n\n```java\npublic static void decrementIndents()\n```\nPermette di decrementare le indentazioni stampate in output prima di un testo passato al metodo *GeneralFormatter.printOut(...)*\n\n```java\npublic static String getIndentes()\n```\nRitorna la stringa composta da tante indentazioni (`\"\\t\"`) quante ce ne sono correntemente.\n\u003c/p\u003e\n\n##### ObjectOutputEngine\nLa classe *ObjectOutputEngine* è una classe non instanziabile, che mette a disposizione 4 metodi statici che permettono di assegnare degli identificatori ai metodi e variabili. La classe deve implementare `ttt.utils.console.output.interfaces.PrintableObject` e le variabili o metodi marcati con l'annotazione `ttt.utils.console.output.annotations.Printable` possono essere utilizzate per rimpiazzare in una stringa il valore associato all'identificatore.\n\nI quattro metodi eseguono sostanzialmente la stessa procedura ma tornano una stringa costruita con criteri differenti:\u003cbr\u003e\ntutti i metodi funzionano secondo prendendo una stringa da formattare (molto simile al funzionamento di `System.out.printf()`) in cui sono presenti delle parole chiave precedute da **%** (ad esempio: *%player* o qualsiasi altra cosa preceduta da *%*).\n\n###### Esempio classi\nPer spiegare in modo semplice il funzionamento segue un esempio completo di utilizzo seguito con la spiegazione dei metodi:\n\n```java\npublic class Posizione implements PrintableObject {\n\n    private final double x;\n    private final double y;\n\n    public Posizione(double x, double y) {\n        this.x = x;\n        this.y = y;\n    }\n\n    @Printable(replace = \"X\")\n    public double getX() {\n        return x;\n    }\n\n    @Printable(replace = \"Y\")\n    public double getY() {\n        return y;\n    }\n\n    @Printable(replace = \"Pos\")\n    @Override\n    public String toString() {\n        return \"(\" + x + \",\" + y + \")\";\n    }\n\n}\n```\n\n```java\npublic class OggettoEsempio implements PrintableObject {\n\n    @Printable(replace = \"TT1\")\n    public String nome = \"Jakson\";\n\n    @Printable(replace = \"TT2\")\n    public char seso = 'M';\n\n}\n```\n\n###### Metodi di formattazione\nNotare come entrambe le classi implementano *PrintableObject*, senza questo passaggio il motore di completamento scarterebbe l'oggetto a priori.\u003cbr\u003e\nL'annotazione *Printable* richiede un parametro: `replace` che prende una stringa, il valore assegnatogli sarà la parola chiave che identifica la variabile o metodo. Nel caso diversi elementi con la stessa parola chiave viene seguito l'ordine con cui vengono passati gli oggetti, e se nello stesso oggetto ci sono più elementi con lo stessa viene seguito l'ordine in cui sono state dichiarate nella classe. Le variabili di classe hanno la priorità sui metodi.\n\nIl metodo `ObjectOutputEngine.printExclusive(...)` ha due overload:\n```java\npublic static String printExclusive(String format, Object o)\n```\n\n```java\npublic static String printExclusive(String format, Object... os)\n```\nPoi sono presenti gli altri due metodi:\n```java\npublic static String print(String format, Object o)\n```\n\n```java\npublic static String printAll(String format, Object... os)\n```\nTutti e quattro prendono in input la stringa da formattare e un'oggetto o la lista di oggetti (che devono implementare *PrintableObject*!!) e ritornano la stringa da formattare ma con le parole chiave sostituite.\u003cbr\u003e\nIl funzionamento tra i 4 metodi è esattamente lo stesso con un'unica eccezione: quelli definiti come *printExclusive* se gli viene passata una stringa che contiene parole chiave non presenti negli oggetti passati come argomento vengono rimosse, mentre quelli non *exclusive* se non trovano una parola chiave la saltano. Segue un'esempio:\n\nOra immaginiamo di eseguire istanziare in questo modo i due oggetti:\n```java\nPosizione pos = new Posizione(5.4, 6.7);\nOggettoEsempio ogg = new OggettoEsempio();\n\nString da_formattare1 = \"La x vale : %X e la y: %Y\";\nString da_formattare2 = \"La posizione di %TT1 è %Pos\";\n```\nVogliamo ora inserire nelle stringhe al posto delle parole-chiave i valori delle istanze.\n\n```java\nString f1 = printExclusive(da_formattare1,pos);\nString f2 = print(da_formattare1,pos);\nString f3 = printExclusive(da_formattare1,ogg);\nString f4 = print(da_formattare1,ogg);\n\nString f5 = printExclusive(da_formattare2,pos);\nString f6 = print(da_formattare2,pos);\n```\n\u003ef1 = \"La x vale: 5.4 e la y: 6.7\"\u003cbr\u003e\n\u003ef2 = \"La x vale: 5.4 e la y: 6.7\"\u003cbr\u003e\n\u003ef3 = \"La x vale:  e la y: \"\u003cbr\u003e\n\u003ef4 = \"La x vale: %X e la y: %Y \"\u003cbr\u003e\u003cbr\u003e\n\u003ef5 = \"La posizione di  è (5.4,6.7)\"\u003cbr\u003e\n\u003ef6 = \"La posizione di %TT1 è (5.4,6.7)\"\u003cbr\u003e\n\nCome si può notare se le funzioni trovano i valori associati ad una parola-chiave lo sostituiscono nella stringa, altrimenti si comportano in modo diverso (*printExclusive* rimuove le parole-chiave non associate ad un valore mentre *print* lascia le parole-chiave nella stringa finale).\u003cbr\u003e\nAllo stesso modo:\n```java\nString f1 = printExclusive(da_formattare2,pos,ogg);\nString f2 = printAll(da_formattare1,pos,ogg);\nString f3 = printExclusive(da_formattare1,ogg);\nString f4 = printAll(da_formattare1,ogg);\n```\n\n\u003ef1 = \"La posizione di Jakson è (5.4,6.7)\"\u003cbr\u003e\n\u003ef2 = \"La posizione di Jakson è (5.4,6.7)\"\u003cbr\u003e\n\u003ef3 = \"La posizione di Jakson è \"\u003cbr\u003e\n\u003ef4 = \"La posizione di Jakson è %Pos\"\u003cbr\u003e\n\nAnche qui le stesse considerazioni fatte per i metodi che prendono un solo oggetto oltre alla stringa come parametro.\n**Da notare: se in una stringa ci sono due parole-chiave uguali non verranno sostituite entrambe con il primo valore associato che si trova ma con gli oggetti successivi.**\nEsempio:\n```java\nPosizione pos1 = new Posizione(5.4, 6.7);\nPosizione pos1 = new Posizione(0.1, 3.3);\n\nString format = \"%Pos %Pos\";\n\nString output = printExclusive(format,pos2,pos1);\n```\n\u003eoutput = \"(0.1,3.3) (5.4,6.7)\"\n\n#### 1.3 Menu:\nContiene una classe d'utilizzo principale: `ttt.utils.console.menu.Menu` che permette di avere un menù dinamico in output nella console per interagire con l'utente.\n\n**Questa classe è *abstract* poiché permette di sovrascrivere i propri metodi per cambiare a piacimento l'interazione con  l'utente.**\n\n###### Istanziare nuovo menù\nLa classe fa uso dei *generics* per poter permettere anche di avere un tipo di ritorno dalla selezione fatta dall'utente. Il menù principale di un'applicazione console dovrebbe essere definito con il tipo `Void` poiché a fine esecuzione teoricamente il programma esce.\u003cbr\u003e\nSono disponibili 2 costruttori:\n```java\npublic Menu(String title)\n```\n```java\npublic Menu(String title, boolean print_menu_title)\n```\nIl primo chiama il secondo passando a *print_menu_title* il valore `false`. Il parametro *title* è semplicemente la stringa che viene stampata come titolo del menu, mentre *print_menu_title* se `true` stampa \"MENU PRINCIPALE\".\u003cbr\u003e\nSegue un'esempio:\n```java\nMenu\u003cVoid\u003e menu = new Menu\u003c\u003e(\"Principale\"){};\n```\n\n###### Rimuovere opzione\nDi default tutti i menù hanno come opzione 1 l'opzione \"Esci\" che non fa altro che chiamare `System.exit(0)`. Per rimuovere un'opzione basta chiamare il metodo `removeOption(int)` passando come parametro l'indice dell'opzione, **ATTENZIONE: questo indice parte da 1 e NON da 0.** Perciò per rimuovere l'opzione \"Esci\" basta fare:\n```java\nMenu\u003cVoid\u003e menu = new Menu\u003c\u003e(\"Principale\"){};\nmenu.removeOption(1);\n```\nEsiste anche `removeOption(Pair\u003cString,FutureAction\u003e)` che permette di rimuovere una coppia precedentemente aggiunta.\n\n###### Trovare indice opzione\nPer trovare a che indice è un'opzione basta chiamare il metodo `optionLookup(String)` che richiede l'esatta voce dell'opzione per poterla trovare e ritorna l'indice dell'opzione, **ATTENZIONE: l'indice ritornato parte da 0.** Usando questo metodo per rimuovere l'opzione \"Esci\" basta fare:\n```java\nMenu\u003cVoid\u003e menu = new Menu\u003c\u003e(\"Principale\"){};\nmenu.removeOption(menu.optionLookup(\"Esci\") + 1);\n```\n\n###### Cambiare voce opzione\nSi può inoltre cambiare la voce di un'opzione sapendo l'esatto testo precedente chiamando `changeOption(String,String)` , per esempio per cambiare \"Esci\" con \"Abbandona\":\n```java\nmenu.changeOption(\"Esci\",\"Abbandona\");\n```\n\n###### Aggiungere opzioni\nPer aggiungere un'opzione esistono 4 overload del metodo `addOption`:\n * Il primo prende prende una stringa e un'interfaccia *FutureAction*;\n * Il secondo un istanza di tipo *Pair\u003cString,FutureAction\u003e*;\n * Il terzo prende un intero (l'indice **che parte da 1 e non 0!**), una stringa e un'interfaccia *FutureAction*;\n * Il quarto prende un intero (l'indice **che parte da 1 e non 0!**) e un istanza di tipo *Pair\u003cString,FutureAction\u003e*;\n\nRispettivamente:\n1.  \n```java\npublic void addOption(String option_message, FutureAction\u003cP\u003e action)\n```\n2.  \n```java\npublic void addOption(Pair\u003cString, FutureAction\u003cP\u003e\u003e option)\n```\n3.  \n```java\npublic void addOption(int index, String option_message, FutureAction\u003cP\u003e action)\n```\n4.  \n```java\npublic void addOption(int index,Pair\u003cString, FutureAction\u003cP\u003e\u003e option)\n```\n\nLa stringa rappresenta la voce con cui verrà mostrata l'opzione in console mentre il codice nel metodo *onSelected* viene eseguito quando l'utente sceglie l'opzione. La *FutureAction\u0026lt;P\u0026gt;* è un'interfaccia generica che in questo caso eredita il *generic* dall'istanza del menù e perciò il metodo *onSelected* deve ritornare un tipo uguale a quello definito per la classe *Menu\u0026lt;P\u0026gt;*.\n\n###### Azioni future (Eseguibili futuri)\nSi possono aggiungere inoltre infinite *FutureAction\u0026lt;P\u0026gt;* che verranno eseguite una sola volta dopo che l'utente seleziona un'opzione, dopo essere state eseguite vengono rimosse perciò è necessario aggiungerle nuovamente. Per aggiungere le interfacce si usa il metodo:\n```java\npublic void addLazyExecutable(FutureAction\u003cP\u003e action)\n```\n###### Reset del menù\nPer reimpostare un menù basta chiamare il metodo `reset()`, questa chiamata rimuove tutte le opzioni precedentemente aggiunte, rimuove inoltre tutti gli eseguibili futuri (lazy executables) oltre a reimpostare il menù sullo stato `quit = false` nel caso fosse stato precedentemente segnato come uscito (fine vita ciclo del menù). Come ultima cosa viene aggiunta nuovamente l'opzione \"Esci\".\n\n###### Eseguire il menù\nEsistono 2 tipi di esecuzione:\n 1. Ciclico: una volta iniziato esistono due modi per terminarlo: *System.exit()* o chiamare il metodo `quit()`;\n\n 2. Singolo: viene mostrato all'utente e una volta che viene scelta l'opzione viene ritornato il valore di esecuzione del metodo *onSelected* dell'interfaccia associata e poi il menù viene terminato.\n\nSi può scegliere come eseguire il menù semplicemente chiamando per (1) `paintMenu()` mentre per (2) `showAndWait()` che ritorna il tipo definito per il menù corrente.\n```java\npublic void paintMenu();\n\npublic P showAndWait();\n```\n###### Funzionalità aggiuntive\nSono presenti inoltre metodi che permettono di modificare minimamente le impostazioni di stampa di un menù:\n1. Questo metodo permette di cambiare il numero di ritorni a capo stampati dopo aver eseguito un'opzione scelta dall'utente (default 3):\n```java\npublic void setDefaultSpaces(int new_value)\n```\n2. Il seguente metodo permette di scegliere se stampare i ritorni a capo oppure no dopo aver eseguito un'opzione e prima di stampare il menù:\n```java\npublic void autoPrintSpaces(boolean value)\n```\n3. Questo metodo segna un menù come finito e non permette di continuare il ciclo di stampa:\n```java\npublic void quit()\n```\n\n###### Chiarimenti\nLa classe `Menu\u003cP\u003e` utilizza la classe *GeneralFormatter* e i suoi metodi per eseguire le stampe in console perciò segue le indentazioni impostate e modificate durante e prima della sua stampa.\n\nSi possono creare sotto-menù semplicemente creando una nuova istanza di `Menu\u003cP\u003e` e facendoli partire quando l'utente sceglie un'opzione del menù padre. Segue un breve esempio:\n```java\n//Creo il menù principale\nMenu\u003cVoid\u003e principale = new Menu\u003c\u003e(\"Menù padre\"){};\n//Aggiungo un'opzione che fa partire un menù secondario\nprincipale.addOption(\"Menu secondrio\",()-\u003e{\n  GeneralFormatter.incrementIndents();\n  //Istanzio un nuovo menù:\n  Menu\u003cInteger\u003e sotto_menu = new Menu\u003c\u003e(\"Menù figlio\"){};\n  //Rimuovo l'opzione \"Esci\"\n  sotto_menu.removeOption(1);\n  //Aggiungo l'opzione per tornare al menù padre\n  sotto_menu.addOption(\"Indietro\",()-\u003e{\n    return null;\n  });\n  //Aggiungo al menù figlio due opzioni che ritornano un valore;\n  sotto_menu.addOption(\"45\",()-\u003e{\n    return 45;\n  });\n  sotto_menu.addOption(\"782\",()-\u003e{\n    return 782;\n  });\n  //Mostro il menù e aspetto il risultato\n  Integer result = sotto_menu.showAndWait();\n  //Controllo se ho un risultato, se null allora l'utente ha scelto \"Indietro\"\n  if(result != null){\n    GeneralFormatter.printOut(\"Valore scelto: \"+ result,true,false);\n  }\n  GeneralFormatter.decrementIndents();\n  return null;//Ricordarsi di tornare un valore!!!!!\n});\n\n//Faccio partire il menù principale in modo ciclico.\nprincipale.paintMenu();\n```\n### 2. Grafi\n(Sezione incompleta)\n\n### 3. Registro\n(Nessuna voglia di spiegarlo per ora)\n\n### 4. XML\nLa gestione di file XML è estremamente automatizzata in questa libreria tanto che basta seguire delle regole generali per riuscire a gestire un qualsiasi tipo di struttura XML.\n\n##### Elementi XML\nTutta la parte di lettura e scrittura si basa su 4 classi principali del package `ttt.utils.xml.document`:\n * XMLElement (implementa tutti e soli i metodi di `ttt.utils.xml.engine.interfaces.IXMLElement`)\n * XMLTag (implementa tutti e soli i metodi di `ttt.utils.xml.engine.interfaces.IXMLTag`)\n * XMLDocument (estende XMLElement)\n * XMLComment **(Opzionale)** (implementa tutti e soli i metodi di `ttt.utils.xml.engine.interfaces.IXMLComment`)\n\nPartendo a spiegare le classi più semplici (le classi,ad eccezione di *XMLDocument* implementano solamente i metodi delle interfacce associate) e di cosa rappresentano:\n1. XMLComment: \u003cbr\u003e\nrappresenta tutti un commento XML definito come:\n  ```xml\n  \u003c!-- Commento --\u003e\n  ```\n * Il costruttore non chiede argomenti.\n * Imposta il testo del commento\n    ```java\n    public void setValue(String value)\n    ```\n * Ritorna il testo contenuto nel commento\n    ```java\n    public String getValue()\n    ```\n2. XMLTag: \u003cbr\u003e\nrappresenta un attributo associato ad un elemento:\n  ```xml\n  \u003celemento tag=\"valore della tag\"/\u003e\n  ```\nDove \"tag\" è il nome della Tag e \"valore della tag\" è il valore testuale associato alla Tag. L'insieme di questi due elementi rappresenta un XMLTag che verrà associata al relativo XMLElement.\n\n * Il costruttore chiede il nome della tag\n    ```java\n    public XMLTag(String name)\n    ```\n * Imposta il nome della tag\n    ```java\n    public void setName(String name)\n    ```\n * Ritorna il nome della tag\n    ```java\n    public String getName()\n    ```\n * Imposta il valore della tag\n    ```java\n    public void setValue(String value)\n    ```\n * Ritorna il valore della tag\n    ```java\n    public String getValue()\n    ```\n3. XMLElement:\u003cbr\u003e\nrappresenta un elemento con tutte le sue tags, il suo valore e i suoi sotto-elementi:\n```xml\n\u003celemento1 tag1=\"value\"\u003e Valore elemento1\n  \u003celemento2\u003e\u003c/elemento2\u003e\n\u003c/elemento1\u003e\n```\nIl seguente codice XML è interpretato come: un *XMLElement* di nome \"elemento1\" che ha una *XMLTag* (con nome \"tag1\" e valore \"value\") che a sua volta ha un *XMLElement* come sotto-elemento. (Ci possono essere infiniti o non essere sotto elementi, stesso vale per le tags e anche per il valore (può esserci ma anche no)).\u003cbr\u003e\nPer questa classe sono implementati molti metodi ma la struttura di funzionamento base è:\n * XMLElement:\u003cbr\u003e\n \u0026nbsp;|-- Nome (uguale al nome dell'elemento nel file)\u003cbr\u003e\n \u0026nbsp;|-- Valore (null se non presente) \u003cbr\u003e\n \u0026nbsp;|-- Mappa di *IXMLTag* (vuota se non presenti tags)\u003cbr\u003e\n \u0026nbsp;|-- Lista di *IXMLElement* (vuota se non presenti sotto elementi)\n\n Quindi per l'esempio precedente:\n * XMLElement:\u003cbr\u003e\n \u0026nbsp;|-- Nome : \"elemento1\"\u003cbr\u003e\n \u0026nbsp;|-- Valore : \"Valore elemento1\" \u003cbr\u003e\n \u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt;\u003cbr\u003e\n \u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- [\"tag1\", XMLTag(\"tag1\",\"value\")]\u003cbr\u003e\n \u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt;\u003cbr\u003e\n \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- XMLElement:\u003cbr\u003e\n \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Nome : \"elemento2\"\u003cbr\u003e\n \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Valore : null\u003cbr\u003e\n \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt; : empty\u003cbr\u003e\n  \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt; : empty\u003cbr\u003e\n\nSperando di aver chiarito come viene costruito un XMLElement ora vengono elencati i metodi:\n\n###### Metodi XMLElement\n* Costruttore: esattamente come per XMLTag prende il nome dell'elemento\n  ```java\n  public XMLElement(String name);\n  ```\n* Attributi base:\n  * nome:\n    ```java\n    public String getName();\n    ```\n  * valore:\n    ```java\n    public void setValue(String value);\n    ```\n    ```java\n    public String getValue();\n    ```\n* Gestione sotto-elementi:\n * aggiunta:\n    ```java\n    public void addSubElement(IXMLElement element);\n    ```\n * rimozione:\n    ```java\n    public void removeSubElement(IXMLElement element);\n    ```\n * controllo:\n    ```java\n    public boolean hasSubElements();\n    public boolean hasElement(IXMLElement element);\n    ```\n * selezione e ricerca:\n    ```java\n    //Ritorna la lista di tutti i sotto-elementi\n    public List\u003cIXMLElement\u003e getElements();\n    //Ritorna la prima occorrenza di un elemento.\n    public IXMLElement getFirstElement(String name);\n    ```\n* Gestione tags:\n  * aggiunta:\n    ```java\n    public void addTag(IXMLTag tag);\n    ```\n\n  * rimozione:\n    ```java\n    public void removeTag(IXMLTag tag);\n    ```\n\n  * controllo:\n    ```java\n    public boolean hasTag(String name);\n    ```\n\n  * selezione e ricerca:\n    ```java\n    public List\u003cIXMLTag\u003e getTags();\n    public IXMLTag getTag(String name);\n    ```\n* Gestione commenti:\n  * aggiunta:\n    ```java\n    public void addComment(IXMLComment comment);\n    ```\n  * selezione:\n    ```java\n    public List\u003cIXMLComment\u003e getComments();\n    ```\n\n4. XMLDocument:\u003cbr\u003e\nrappresenta il documento intero. Questa libreria considera il documento stesso un elemento perciò questa classe estende ed eredita tutti i metodi e valori di `XMLElement`.\u003cbr\u003e\nBisogna tenere presente che un documento XML contiene al massimo 1 elemento che rappresenta la *root* perciò la lista di sotto-elementi ereditata dalla classe padre conterrà solamente un elemento, per l'appunto la radice.\u003c/p\u003e\nI metodi aggiunti sono:\n\n* Costruttore che chiede il file di output/input (può anche non esistere o essere `null`):\n  ```java\n  public XMLDocument(File file);\n  ```\n  Per prendere il file impostato chiamare il metodo:\n  ```java\n  public File getSourceFile();\n  ```\n\n* Ritornare l'elemento *root*:\n  ```java\n  public IXMLElement getRoot();\n  ```\n\n##### Lettura e scrittura XML\nPer adempiere a queste due funzioni si utilizzano le due classi del package `ttt.utils.xml.io`:\n * XMLReader\n * XMLWriter\n\n###### Scrittura\nPer scrivere file XML la libreria offre una comoda classe che permette in modo automatico di scrivere un XMLDocument: `XMLWriter`. \u003cbr\u003e\nLa classe è di facile utilizzo, mette a disposizione:\n* Il costruttore chiede un solo parametro di tipo *File* che rappresenta il file di output in cui verrà scritto il contenuto.\n* Il metodo per scrivere il documento su file:\n```java\npublic void writeDocument(XMLDocument document, boolean hr);\n```\nIl metodo prende come parametro il documento XMLDocument (*document*) da scrivere (in modo ricorsivo scriverà tutti i sotto-elementi con le relative tags e valori). Il parametro *hr* è l'abbreviazione per \"Human Readable\", se il valore `hr = true` allora il file viene stampato con la formattazione corretta (ritorni a capo e indentazioni) altrimenti viene stampato tutto il contenuto in modo più compatto su una singola riga.\n\nLa scrittura automatica supporta tutti gli elementi annotati da `MethodType` con valore impostato su *MethodType.GET* e quelli con `FieldType` impostati su *FieldType.WRITE* oppure *FieldType.READ_AND_WRITE*.\u003cbr\u003e\n (Questa parte verrà affrontata più avanti trattando del motore di lettura e conversione XML)\n\n###### Lettura\nCome per la classe di scrittura anche la classe di letture `XMLReader` è di facile utilizzo. Questa classe permette di caricare da un *File* o da un *InputStream* il contenuto XML e caricarlo in un XMLDocument composto da una radice a sua volta composta da tutti i sotto-elementi ricostruiti in maniera ricorsiva (vengono inclusi tutti i commenti, le tags e i valori, e naturalmente i sotto-elementi).\nLa classe mette quindi a disposizione:\n* Il costruttore che chiede un solo parametro di tipo *File* che rappresenta il file di input da cui verrà estratto il contenuto.\n* Il costruttore che chiede un solo parametro di tipo *InputStream* che rappresenta lo stream da cui estrarre il contenuto XML.\n* Il metodo per leggere il documento:\n```java\npublic XMLDocument readDocument() throws IOException;\n```\nIl metodo non prende parametri e ritorna il documento XMLDocument (*document*) letto dal file (o stream) in cui viene ricostruita tutta la struttura tramite liste di `XMLElement` contenenti a loro volta `XMLTag` e `XMLComment` e valori, oltre ad altri `XMLElement` se nel file sono presenti sotto-elementi.\n\nLa lettura automatica supporta tutti gli elementi annotati da `MethodType` con valore impostato su *MethodType.SET* e quelli con `FieldType` impostati su *FieldType.READ* oppure *FieldType.READ_AND_WRITE*.\u003cbr\u003e\n (Questa parte verrà affrontata più avanti trattando del motore di lettura e conversione XML)\n\n Segue un esempio di lettura e trascrittura di un file XML (*\"input.xml\"* a *\"output.xml\"*):\n ```java\n try {\n   //Creazione lettore file\n     XMLReader reader = new XMLReader(new File(\"input.xml\"));\n   //Lettura del file in XMLDocument\n     XMLDocument doc = reader.readDocument();\n   //Creazione scrittore file\n     XMLWriter writer = new XMLWriter(new File(\"output.xml\"));\n   //Scrittura del documento letto\n     writer.writeDocument(doc, true);\n } catch (IOException ex) {\n   //Eccezione nella letture del file\n }\n ```\n\n\u003cp\u003e\n Arrivati a questo punto la lettura e scrittura base di un file XML è stata trattata.\n\n Si può continuare creando *XMLElement* (anche *XMLTag* ma anche *XMLComment* (superfluo e non verrà mostrato ma il concetto rimane invariato)) personalizzati e utilizzare strutture di controllo.\n \u003c/p\u003e\n\n##### XMLEngine\nViene messo a disposizione un motore che permette di trasformare un generico *XMLDocument* letto (dove per generico si intende composto da N istanze di *XMLElement*) in un documento specifico (dove per specifico si intende composto da N istanze di classi personalizzate che estendono *XMLElement*).\n\nViene innanzitutto mostrato come e con che criterio devono essere realizzate le classi specifiche di *XMLElement*. Le regole **obbligatorie per un corretto funzionamento** sono le seguenti:\n* la classe in questione deve estendere la classe *XMLElement* evitando di fare l'override dei metodi per non incorrere in errori inaspettati (difficilmente vengono scatenate eccezioni e molto più probabilmente si incontrano comportamenti indesiderati);\n* la classe deve avere un costruttore vuoto (senza parametri) che chiama il costruttore `super(stringa)` passando alla variabile *stringa* il nome del componente da associare (**attenzione, la stringa è case-sensitive: le maiuscole fanno la differenza**);\n* la classe deve essere annotata con l'annotazione `Element` del package `ttt.utils.xml.engine.annotations`. L'annotazione deve avere il parametro *Name* con assegnata una stringa **esattamente identica** a quella passata nel costruttore alla chiamata di *`super(stringa)`*.\n\nPrendendo ad esempio il file XML contentente:\n```xml\n\u003celemento1 tag1=\"value\"\u003e Valore elemento1\n\t\u003celemento2\u003eValore 1\u003c/elemento2\u003e\n\t\u003celemento2\u003eValore 2\u003c/elemento2\u003e\n\u003c/elemento1\u003e\n```\n\nSi **possono** (non è obbligatorio, ma per avere un miglior controllo è consigliato farlo) creare 2 classi: una per ogni tipologia di elemento presente nel file, in questo caso per: *elemento1* e *elemento2*:\n```java\n@Element(Name = \"elemento1\")\npublic class ElementoPrincipale extends XMLElement {\n    public ElementoPrincipale() {\n        super(\"elemento1\");\n    }\n}\n```\n```java\n@Element(Name = \"elemento2\")\npublic class ElementoSecondario extends XMLElement {\n    public ElementoSecondario() {\n        super(\"elemento2\");\n    }\n}\n```\nCome si può notare le stringhe passate alle annotazioni e ai costruttori sono **esattamente identiche** ai nomi degli elementi nel file. Nel caso le stringhe non siano uguali la classe diventa inutilizzata.\n\nIl funzionamento del motore è relativamente semplice: letto un documento sostituisce gli *XMLElement* caricati con le classi che estendono *XMLElement* e hanno come nome dell'elemento lo stesso di quello letto (per questo motivo è necessario che siano identiche le stringhe).\n\nL'utilizzo della classe `XMLEngine` è estremamente semplice, sono presenti 3 tipi di costruttori:\n* tramite File;\n* tramite XMLReader;\n* tramite XMLDocument;\n\nTutti chiedono una lista di classi, queste sono le classi che si vogliono utilizzare per sostituire in un documento gli *XMLElement*.\nUtilizzando l'esempio di prima basta estenderlo di poco per convertire un documento\n```java\ntry {\n\t//Creazione lettore file\n\tXMLReader reader = new XMLReader(new File(\"input.xml\"));\n\t//Lettura del file in XMLDocument\n\tXMLDocument da_convertire = reader.readDocument();\n\t//Creo un nuovo documento che conterrà il file convertito in classi personalizzate\n\tXMLDocument convertito = new XMLDocument(null);\n\t//Creo il nuovo motore di conversione passando l'XMLDocument da convertire e le classi desiderate \n\tXMLEngine eng = new XMLEngine(da_convertire,ElementoPrincipale.class,ElementoSecondario.class);\n\t//Converto il documento e lo salvo nel documento vuoto creato prima\n\teng.morph(convertito);\n\t//Da qui in poi \"convertito\" è l'XMLDocument contenente la lista di XMLElement personalizzati\n\t//La scrittura viene omessa per ora...\n} catch (IOException ex) {\n\t//Eccezione nella letture del file\n}\n```\nFacendo così tutti gli XMLElement presenti in *\"da_convertire\"* che avevano un nome presente nella lista di classi passati al motore sono stati convertiti. La struttura cambia perciò da così:\n\n***XMLElement***:\u003cbr\u003e\n\u0026nbsp;|-- Nome : \"elemento1\"\u003cbr\u003e\n\u0026nbsp;|-- Valore : \"Valore elemento1\" \u003cbr\u003e\n\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt;\u003cbr\u003e\n\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- [\"tag1\", XMLTag(\"tag1\",\"value\")]\u003cbr\u003e\n\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt;\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ***XMLElement***:\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Nome : \"elemento2\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Valore : \"Valore 1\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt; : empty\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt; : empty\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ***XMLElement***:\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Nome : \"elemento2\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Valore : \"Valore 2\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt; : empty\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt; : empty\u003cbr\u003e\n\na così:\n\n***ElementoPrincipale***:\u003cbr\u003e\n\u0026nbsp;|-- Nome : \"elemento1\"\u003cbr\u003e\n\u0026nbsp;|-- Valore : \"Valore elemento1\" \u003cbr\u003e\n\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt;\u003cbr\u003e\n\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- [\"tag1\", XMLTag(\"tag1\",\"value\")]\u003cbr\u003e\n\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt;\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ***ElementoSecondario***:\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Nome : \"elemento2\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Valore : \"Valore 1\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt; : empty\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt; : empty\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- ***ElementoSecondario***:\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Nome : \"elemento2\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Valore : \"Valore 2\"\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- Map\u0026lt;IXMLTag\u0026gt; : empty\u003cbr\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;|-- List\u0026lt;IXMLElement\u0026gt; : empty\u003cbr\u003e\n\n###### Perchè conviene utilizzare delle classi personalizzate?\n1. Perchè nelle classi personalizzate si possono definire variabili e metodi che possono aiutare la scrittura e gestione del programma che non sono concepiti per la lettura e scrittura XML;\n2. Perchè si possono avere le variabili di classe (ma anche metodi) chiamati e assegnati con valori delle tags di un elemento;\n3. Perchè si possono utilizzare le strutture di controllo;\n4. Per avere una gestione e integrazione migliorata dei file XML con il programma.\n\n###### Tags collegate a variabili di classe\nPer collegare una XMLTag (una tag letta di un elemento) ad una variabile basta utilizzare le annotazioni:\n* `Tag` del package `ttt.utils.xml.engine.annotations`;\n* `FieldType` del package `ttt.utils.engines.interfaces`;\n\nLa prima annotazione (`Tag`) definisce a che *Tag* la variabile verrà associata, la seconda (`FieldType`) definisce in che maniera viene gestita:\n* *FieldType.READ* la variabile viene solamente caricata nella variabile quando viene convertito il documento da file a XMLDocument;\n* *FieldType.WRITE* la variabie non viene caricata ma alla scrittura del file viene scritta al relativo elemento;\n* *FieldType.READ_AND_WRITE* la variabile viene sia letta che scritta;\n\nSegue l'estensione dell'esempio precedente della classe *ElementoPrincipale*:\n```java\n@Element(Name = \"elemento1\")\npublic class ElementoPrincipale extends XMLElement {\n\n\t@EngineField(FieldType = FieldType.READ_AND_WRITE)\n    @Tag(Name = \"tag1\", ValueType = String.class)\n    private String tag_principale;\n\n    public ElementoPrincipale() {\n        super(\"elemento1\");\n    }\n\t\n}\n```\n\nEsaminando l'annotazione `Tag`:\n* Il parametro `Name` è obbligatorio e **deve essere identico al nome della tag nel file** \n* Il parametro `ValueType` prende la classe che rappresenta la tag: nel caso la tag contenenga, ad esempio, un valore intero basta dichiarare nel modo seguente la tag e viene eseguito un cast automatico (**supponendo quindi che la tag \"tag1\" contenga un valore intero**):\n```java\n@Element(Name = \"elemento1\")\npublic class ElementoPrincipale extends XMLElement {\n\n\t@EngineField(FieldType = FieldType.READ_AND_WRITE)\n    @Tag(Name = \"tag1\", ValueType = int.class)\n    private int tag_principale;\n\n    public ElementoPrincipale() {\n        super(\"elemento1\");\n    }\n}\n```\n\n\nSi possono definire quante variabili si vogliono e non è obbligatorio dichiarare una variabile per ogni tag.\n\n###### Tags collegate a metodi di classe e metodi di calcolo\nAllo stesso modo si possono collegare dei metodi in modo tale da prendere tags oppure definirsi come metodi di \"calcolo\". I metodi che vengono collegati ad una tag vengono chiamati alla lettura (subito dopo la chiamata al costruttore), tutti quelli definiti come di tipo \"calcolo\" vengono chiamati alla fine della compilazione delle tags.\n\nRiprendendo l'esempio precedente:\n```java\n@Element(Name = \"elemento1\")\npublic class ElementoPrincipale extends XMLElement {\n\n    private String tag_principale;\n\n    public ElementoPrincipale() {\n        super(\"elemento1\");\n    }\n\t\n\t@EngineMethod(MethodType = MethodType.SET)\n    @Tag(Name = \"tag1\", ValueType = String.class)\n\tpublic void impostaValore(String s){\n\t\tthis.tag_principale = s;\n\t}\n\t\n}\n```\n\nAnche qui vengono fatte le stesse considerazioni per il metodo:\n* Il metodo deve avere **un solo parametro** e il tipo del parametro deve corrispondere a quello definito in *ValueType* della `Tag` (anche qui in caso di valori diversi da *String* viene eseguito un cast)\n* Il valore per *Name* deve essere esattamente identico al nome della tag nel file, altrimenti il metodo non verrà mai chiamato.\n\nIl metodo  \"impostaValore\" rappresenta l'equivalente di *FieldType.READ* volendo emulare il funzionamento di *FieldType.WRITE* bisogna definire un metodo get:\n```java\n...\n@EngineMethod(MethodType = MethodType.GET)\n@Tag(Name = \"tag1\", ValueType = String.class)\npublic String leggiValore(){\n\treturn this.tag_principale;\n}\n...\n```\n\nRicordandosi che qui il metodo **non** prende parametri e il tipo di ritorno è identico a quello definito in *ValueType* della `Tag`.\n\n##### Strutture di controllo\nLe strutture di controllo permettono di verificare la correttezza di un file XML. L'utilizzo è relativamente intuitivo, si utilizzano le classi:\n* StructureModule (del package `ttt.utils.xml.document.structure`)\n* Rules (del package `ttt.utils.xml.document.structure.rules`)\n* Structure (del package `ttt.utils.xml.document.structure`)\n\n###### Modulo di struttura\nIl modulo di una struttura rappresenta una sezione di regole che il file deve rispettare. I moduli sono da costruire secondo la struttura del file desiderata. \n\nAd esempio: si vuole controllare che il file contenga un elemento radice di tipo *ElementoPrincipale*(\"elemento1\") che a sua volta contenga da 1 a infiniti elementi del tipo *ElementoSecondario*(\"elemento2\") che a loro volta contengono un solo o nessuno elemento del tipo *ElementoTerziario*(\"elemento3\"):\n\n\n* Questa struttura risulta corretta:\n```xml\n\u003celemento1 tag1=\"value\"\u003e Valore elemento1\n\t\u003celemento2\u003eValore 1\u003c/elemento2\u003e\n\t\u003celemento2\u003eValore 2\u003c/elemento2\u003e\n\u003c/elemento1\u003e\n```\n\n* Questa struttura risulta corretta:\n```xml\n\u003celemento1 tag1=\"value\"\u003e Valore elemento1\n\t\u003celemento2\u003e\n\t\t\u003celemento3\u003e1212941238\u003c/elemento3\u003e\n\t\u003c/elemento2\u003e\n\t\u003celemento2\u003eValore 2\u003c/elemento2\u003e\n\u003c/elemento1\u003e\n```\n\n* Questa struttura risulta errata:\n```xml\n\u003celemento1 tag1=\"value\"\u003e Valore elemento1\n\t\u003celemento2\u003e\n\t\t\u003celemento3\u003e1236623\u003c/elemento3\u003e\n\t\t\u003celemento3\u003e1212941238\u003c/elemento3\u003e\n\t\u003c/elemento2\u003e\n\t\u003celemento2\u003eValore 2\u003c/elemento2\u003e\n\u003c/elemento1\u003e\n```\n\nCome si controlla? Semplicemendo concatenando diversi `StructureModule` con le corrispettive regole:\n```java\nStructureModule principale = new StructureModule(ElementoPrincipale.class, Rules.ONE);\nStructureModule secondario = new StructureModule(ElementoSecondario.class, Rules.ONE_TO_INFINITE);\nStructureModule terziario = new StructureModule(ElmentoTerziario.class, Rules.ZERO_TO_ONE);\n\nsecondario.addModule(terziario);\nprincipale.addModule(secondario);\n```\n\nOppure in maniera uguale ma più compatta:\n```java\nStructureModule principale \n= new StructureModule(ElementoPrincipale.class, Rules.ONE)\n\t\t\t.addModule(new StructureModule(ElementoSecondario.class, Rules.ONE_TO_INFINITE)\n\t\t\t\t.addModule(new StructureModule(ElmentoTerziario.class, Rules.ZERO_TO_ONE)));\n```\n\n###### Controllo struttura\nDefinito lo `StructureModule` principale che contiene tutti gli altri moduli si definisce una variabile di tipo `Structure` gli si **gli si imposta il modulo principale** e si verifica la struttura:\n```java\nStructureModule principale \n= new StructureModule(ElementoPrincipale.class, Rules.ONE)\n\t\t\t.addModule(new StructureModule(ElementoSecondario.class, Rules.ONE_TO_INFINITE)\n\t\t\t\t.addModule(new StructureModule(ElmentoTerziario.class, Rules.ZERO_TO_ONE)));\n\t\t\t\t\n\t\t\t\t\nStructure s = new Structure();\ns.setStructureModel(principale);\n\ntry{\n\ts.verify(documentoXML_letto_e_convertito);\n}catch(InvalidXMLFormat | UninitializedMandatoryProperty ex){\n\t//Gestione: se InvalidXMLFormat allora la struttura del file è errata e non rispetta uno dei moduli\n}\n```\n\nIl metodo *verifiy(XMLDocument)* controlla la correttezza di un documento **letto e convertito con le classi corrette**, nel caso la struttura non sia corretta lancia l'eccezione *InvalidXMLFormat*.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabri-viane%2Futils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgabri-viane%2Futils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabri-viane%2Futils/lists"}