' PlantUML: tool per la generazione di UML (.png) in modo testuale
' supporta diversi diagrammi UML 
' (es. diagramma delle classi, di sequenza...)
' esempio file plantuml.txt per generare UML a destra
' download (jar): http://plantuml.com/download
' documentazione: http://plantuml.com/class-diagram

@startuml

title Esempio Operazioni - Class Diagram

class MainOperazioni 

class Operazione {
	# valori : List 
	# parsaOperandi() : void
	+ {abstract} calcolaRisultato() : float
}

class Somma {
	+ calcolaRisultato() : float
}

class Moltiplicazione {
	+ calcolaRisultato() : float
}

class ListaOperazioni {
	- listaOperazioni : List
	+ leggiFile() : void
	+ inserisci(riga : String) : void
	+ calcolaTotale() : float
	+ svuota() : void
}

hide MainOperazioni members

Operazione <|-down- Somma
Operazione <|-down- Moltiplicazione
MainOperazioni -right-> ListaOperazioni
ListaOperazioni o-right- Operazione 

@enduml
diagramma UML delle classi
// Operazione.java
// contiene annotazioni per guidare la generazione della javadoc
// usare javadoc *.java per generare la documentazione per tutti  
// i sorgenti (anche per quelli non annotati)
import java.util.ArrayList;
import java.util.List;

/**
 * Classe astratta usata per gestire un operazione di calcolo 
 * su di una lista di valori (operandi). La logica dell'operazione 
 * di calcolo viene definita nelle sotto-classi.  
 * 
 * @author Andrea Fornaia
 * 
 */
public abstract class Operazione {
	/**
	 * Lista degli operandi usati per il calcolo del risultato.
	 * 
	 */
	protected List valori = new ArrayList<>();
	
	public Operazione(String operandi) {
		parsaOperandi(operandi);
	}
	
	/**
	 * Effettua il parsing della lista degli operandi. Il comportamento di
	 * default e' di aggiungere ogni elemento alla lista dei valori. Puo' essere ridefinito.
	 * 
	 * @param operandi stringa contenente la lista di operandi separati da ','.
	 */
	protected void parsaOperandi(String operandi) {
		for (String s: operandi.split(",")) {
			valori.add(Float.parseFloat(s));
		}
	}
	
	/**
	 * Calcola il risultato dell'operazione. Dovrebbe utilizzare la lista di valori.
	 * 
	 * @return risultato dell'operazione.
	 */
	public abstract float calcolaRisultato(); 
	
}
// Somma.java
public class Somma extends Operazione {

	public Somma(String operandi) {
		super(operandi);
	}

	/**
	 * Calcola il risultato dell'operazione Somma. Utilizzare la lista di valori.
	 * 
	 * @return risultato dell'operazione.
	 */
	@Override
	public float calcolaRisultato() {
		float result = 0;
		
		for (float f : valori) {
			result += f;
		}
		return result;
	}
}
// Moltiplicazione.java
public class Moltiplicazione extends Operazione {

	public Moltiplicazione(String operandi) {
		super(operandi);
	}

	@Override
	public float calcolaRisultato() {
		float result = 1;
		
		for (float f : valori) {
			result *= f;
		}
		
		return result;
	}
}

// classe che chiama metodi di ListaOperazioni
// compilare con javac MainOperazioni.java
// eseguire con java MainOperazioni
import java.io.IOException;

public class MainOperazioni {
	public static void main(String[] args) {
		System.out.println("inizio esecuzione");
		ListaOperazioni lsop = new ListaOperazioni();

		try {
			lsop.leggiFile("csvfiles", "Operazioni.csv");
		} catch (IOException e) {
			System.err.println(e.getMessage());
			return;
		}
		
		System.out.println("somma totale "+ lsop.calcolaSommaTotale());
	}
}
// ListaOperazioni.java
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;

public class ListaOperazioni {
	List listaOperazioni = new ArrayList<>();
	
	public void leggiFile(String c, String n) throws IOException {
		LineNumberReader f = new LineNumberReader(new FileReader(new File(c, n)));
		String riga;
		while (true) {
			riga = f.readLine();          // legge una linea dal file
			if (riga == null) break;      // controlla se il file e' finito
			inserisci(riga);
		}
		f.close();
	}

	public void inserisci(String riga) throws IOException {
		String operazione = parseOperazione(riga);
		String operandi = parseOperandi(riga);
		
		switch (operazione) {
			case "SUM":
				listaOperazioni.add(new Somma(operandi));
				break;
			case "MUL":
				listaOperazioni.add(new Moltiplicazione(operandi));
				break;
			default:
				throw new IOException("Errore di parsing: Operazione sconosciuta " + operazione);
		}
	}

	private String parseOperazione(String riga) {
		return riga.substring(0, riga.indexOf(","));
	}

	private String parseOperandi(String riga) {
		return riga.substring(riga.indexOf(",") + 1);
	}
	
	public float calcolaSommaTotale() {
		float risultato = 0;
	
		for (Operazione op : listaOperazioni) {
			risultato += op.calcolaRisultato();
		}
		
		return risultato;
	}
	
	public void svuota() {
		listaOperazioni = new ArrayList<>();
	}

}
// classe che testa i metodi di ListaOperazioni
// compilare con javac TestListaOperazioni.java
// eseguire con java TestListaOperazioni
import java.io.IOException;

public class TestListaOperazioni {
	private ListaOperazioni lsop = new ListaOperazioni();
	
	private void initLista() {
		lsop.svuota();
		try {
			lsop.inserisci("SUM,1,2,3,4");	// res: 10 
			lsop.inserisci("MUL,1,2,3,4");	// res: 24
		} catch (IOException e) { 
			System.out.println(e.getMessage());
		}
	}
	
	public void testLeggiFile() {
		lsop.svuota();
		try {
			lsop.leggiFile("csvfiles", "Operazioni.csv"); 
			System.out.println("OK testLeggiFile");
		} catch (IOException e) {
			System.out.println("FAILED testLeggiFile");
		}
	}
	
	public void testInserisciSum() {
		lsop.svuota();
		try {
			lsop.inserisci("SUM,1,2,3,4");
			System.out.println("OK testInserisciSum");
		} catch (IOException e) {
			System.out.println("FAILED testInserisciSum");
		}		
	}
	
	public void testInserisciMul() {
		lsop.svuota();
		try {
			lsop.inserisci("MUL,1,2,3,4");
			System.out.println("OK testInserisciMul");
		} catch (IOException e) {
			System.out.println("FAILED testInserisciMul");
		}
	}
	
	public void testInserisciSconosciuto() {
		lsop.svuota();
		try {
			lsop.inserisci("ABC,1,2,3,4");
			System.out.println("FAILED testInserisciSconosciuto");
		} catch (IOException e) {
			System.out.println("OK testInserisciSconosciuto");
		}
	}
	
	private void testCalcolaSommaTotale() {
		initLista();
		if (lsop.calcolaSommaTotale() == 34f)
			System.out.println("OK testCalcolaSommaTotale");
		else
			System.out.println("FAILED testCalcolaSommaTotale");
	}
	
	public static void main(String[] args) {
		TestListaOperazioni t = new TestListaOperazioni();
		t.testLeggiFile();
		t.testInserisciMul();
		t.testInserisciSum();
		t.testInserisciSconosciuto();
		t.testCalcolaSommaTotale();
	}
}