Dokumentation

This commit is contained in:
ngb
2022-12-08 21:16:01 +01:00
parent 8de3c41b9b
commit 9fc58b05b6
6 changed files with 267 additions and 59 deletions

View File

@@ -5,7 +5,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Eine Hilfsklasse um Dinge zu zählen.
* Eine Helferklasse, um Dinge zu zählen.
* <p>
* Im einfachsten Fall kann der Zähler als geteilte Zählvariable genutzt werden,
* die mit {@link #inc()} und {@link #dec()} aus verschiedenen Objekten oder
@@ -13,11 +13,11 @@ import java.util.concurrent.atomic.AtomicInteger;
* <p>
* Der Zähler kann aber auch Objekte zählen, indem die Instanzen an
* {@link #count(Object)} übergeben werden. Am Ende kann mit {@link #getCount()}
* die Anzahl der Objkete abgerufen werden.
* die Anzahl der Objekte abgerufen werden.
* <p>
* Handelt es sich bei den Objekten um Zahlen, dann merkt sich ein Zähler auch
* das Maximum, das Minimum, die Summe und den Durchschnitt der gezählten
* Werte.
* Handelt es sich bei den Objekten um Zahlen, dann merkt sich ein
* {@code Counter} auch das Maximum, das Minimum, die Summe und den Durchschnitt
* der gezählten Werte.
* <p>
* Ein Zähler kann auch komplette Arrays oder Listen von Zahlen zählen und die
* obigen Statistiken auswerten.
@@ -96,31 +96,42 @@ public final class Counter {
}
/**
* Gibt die aktuelle Anzahl zurück.
* @return Die aktuelle Anzahl.
*/
public int getCount() {
return count.get();
}
/**
* @return Das Maxium der bisher gezählten Werte.
*/
public double getMax() {
synchronized( count ) {
return max;
}
}
/**
* @return Das Minimum der bisher gezählten Werte.
*/
public double getMin() {
synchronized( count ) {
return min;
}
}
/**
* @return Die Summe der bisher gezählten Werte.
*/
public double getSum() {
synchronized( count ) {
return sum;
}
}
/**
* @return Der Mittelwert der bisher gezählten Werte.
*/
public double getAvg() {
if( Double.isNaN(sum) ) {
return Double.NaN;
@@ -129,13 +140,27 @@ public final class Counter {
}
}
/**
* Setzt den Zähler auf den angegebenen Wert.
* <p>
* Die anderen Statistiken werden nicht verändert.
*
* @param count Der neue Wert des Zählers.
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter setCount( int count ) {
this.count.set(count);
return this;
}
/**
* Setzt den Zähler auf Null.
* <p>
* Die Statistiken werden auf {@link Double#NaN} gesetzt.
*
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter reset() {
count.set(0);
@@ -147,18 +172,40 @@ public final class Counter {
return this;
}
/**
* Erhöht den Zähler um Eins.
* <p>
* Die anderen Statistiken werden nicht verändert.
*
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter inc() {
this.count.incrementAndGet();
return this;
}
/**
* Verringert den Zähler um Eins.
* <p>
* Die anderen Statistiken werden nicht verändert.
*
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter dec() {
this.count.decrementAndGet();
return this;
}
/**
* Zählt den angegebenen Wert.
* <p>
* Erhöht den Zähler um Eins und aktualisiert die Statistiken.
*
* @param value Der neue Wert.
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter count( double value ) {
inc();
@@ -173,11 +220,27 @@ public final class Counter {
return this;
}
/**
* Zählt die angegebene Zahl.
* <p>
* Erhöht den Zähler um Eins und aktualisiert die Statistiken.
*
* @param num Die neue Zahl.
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter count( Number num ) {
return count(num.doubleValue());
}
/**
* Zählt das angegebenen Objekt.
* <p>
* Erhöht den Zähler um Eins.
*
* @param obj Ein beliebiges Objekt.
* @return Dieser Zähler selbst (method chaining).
*/
@SuppressWarnings( "UnusedReturnValue" )
public Counter count( Object obj ) {
if( obj instanceof Number ) {
@@ -188,6 +251,13 @@ public final class Counter {
}
}
/**
* Zöhlt alle Werte im angegebenen Array.
*
* @param values Das Array der neuen Werte.
* @return Dieser Zähler selbst (method chaining).
* @see #count(double)
*/
@SuppressWarnings( "UnusedReturnValue" )
public synchronized Counter countAll( double[] values ) {
for( double value : values ) {
@@ -196,6 +266,13 @@ public final class Counter {
return this;
}
/**
* Zöhlt alle Werte im angegebenen Array.
*
* @param values Das Array der neuen Werte.
* @return Dieser Zähler selbst (method chaining).
* @see #count(double)
*/
@SuppressWarnings( "UnusedReturnValue" )
public synchronized Counter countAll( int[] values ) {
for( double value : values ) {
@@ -204,6 +281,13 @@ public final class Counter {
return this;
}
/**
* Zöhlt alle Zahlen im angegebenen Array.
*
* @param values Das Array der neuen Zahlen.
* @return Dieser Zähler selbst (method chaining).
* @see #count(Number)
*/
@SuppressWarnings( "UnusedReturnValue" )
public synchronized Counter countAll( Number[] values ) {
for( Number value : values ) {
@@ -212,6 +296,13 @@ public final class Counter {
return this;
}
/**
* Zöhlt alle Zahlen in der angegebenen Sammlung.
*
* @param values Die Sammlung der neuen Zahlen.
* @return Dieser Zähler selbst (method chaining).
* @see #count(Number)
*/
@SuppressWarnings( "UnusedReturnValue" )
public synchronized Counter countAll( Collection<Number> values ) {
for( Number value : values ) {

View File

@@ -3,7 +3,7 @@ package schule.ngb.zm.util;
import java.util.Random;
/**
* Zufallsgenerator für Perlin-Noise.
* Generator für Perlin-Noise.
* <p>
* Die Implementierung basiert auf dem von Ken Perlin entwickelten Algorithmus
* und wurde anhand der <a
@@ -18,7 +18,7 @@ public class Noise {
private static final int M = N - 1;
/**
* Interne Permutationstabelle für diesen Generator
* Interne Permutationstabelle für diesen Generator.
*/
private int[] p;

View File

@@ -3,13 +3,13 @@ package schule.ngb.zm.util;
import java.util.concurrent.TimeUnit;
/**
* Eine Hilfsklasse zur Zeitmessung im Nanosekundenbereich.
* Helferklasse zur Zeitmessung im Nanosekundenbereich.
* <p>
* Die Klasse kann zum Beispiel genutzt werden, um die Laufzeit eines
* Quelltextes zu messen. Wie eine echte Stoppuhr läuft der {@code Timer}
* weiter, wenn nach einem {@link #stop()} wieder {@link #start()} aufgerufen
* wird. Soll die Zeitmessung wieder bei null beginnen, muss vorher
* {@link #reset()} genutzt werden.
* Mit einem {@code Timer} kann zum Beispiel die Laufzeit eines Algorithmus
* gemessen werden. Wie eine echte Stoppuhr läuft der {@code Timer} weiter, wenn
* nach einem {@link #stop()} wieder {@link #start()} aufgerufen wird. Soll die
* Zeitmessung wieder bei null beginnen, muss vorher {@link #reset()} genutzt
* werden.
* <p>
* Die gemessene Zeit kann in {@link #getMillis() Millisekunden} oder
* {@link #getSeconds() Sekunden} abgerufen werden. Wird eine noch größere
@@ -100,7 +100,7 @@ public final class Timer {
}
/**
* Stoppt den {@code Timer}, wenn er derzeit läuft. Die gemessene Zeit wird
* Stoppt den {@code Timer}, wenn er derzeit läuft. Die gemessene Dauer wird
* zur Summe aller gemessenen Zeiten hinzuaddiert.
*
* @return Dieser {@code Timer} selbst (method chaining).
@@ -116,8 +116,8 @@ public final class Timer {
/**
* Setzt den {@code Timer} auf den Startzustand und löscht alle bisher
* gemessenen Zeiten. Falls die Zeitmessung gerade läuft, wird sie nicht
* gestoppt, sondern läuft vom Zeitpunkt des Aufrufs weiter.
* gemessenen Zeiten. Falls die Zeitmessung gerade läuft, stoppt sie nicht,
* sondern startet vom Zeitpunkt des Aufrufs neu.
*
* @return Dieser {@code Timer} selbst (method chaining).
*/

View File

@@ -3,6 +3,9 @@ package schule.ngb.zm.util;
import java.util.Objects;
import java.util.function.Supplier;
/**
* Statische Methoden, um Methodenparameter auf Gültigkeit zu prüfen.
*/
@SuppressWarnings( "UnusedReturnValue" )
public class Validator {

View File

@@ -4,37 +4,63 @@ import schule.ngb.zm.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import java.util.function.Function;
/**
* Helferklasse, um Textdateien in verschiedenen Formaten einzulesen.
*/
@SuppressWarnings( "unused" )
public final class FileLoader {
/**
* Charset: ASCII
*/
public static final Charset ASCII = StandardCharsets.US_ASCII;
/**
* Charset: UTF-8
*/
public static final Charset UTF8 = StandardCharsets.UTF_8;
/**
* Charset: UTF-16
*/
public static final Charset UTF16 = StandardCharsets.UTF_16;
/**
* Charset: ISO-8859-1
*/
public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
/**
* Lädt die angegebene Textdatei zeilenweise in eine Liste.
* <p>
* Als {@link Charset} wird {@link #UTF8} verwendet.
*
* @param source Die Quelle der Textdatei.
* @return Eine Liste mit den Zeilen der Textdatei.
* @see #loadLines(String, Charset)
*/
public static List<String> loadLines( String source ) {
return loadLines(source, UTF8);
}
/**
* Lädt die angegebene Datei Zeilenweise in eine Liste.
* Lädt die angegebene Textdatei mit dem angegebenen Charset zeilenweise in
* eine Liste.
* <p>
* Am Ende jeder Zeile wird das Symbol für einen Zeilenumbruch ({@code \n})
* entfernt.
*
* @param source
* @param charset
* @return
* @param source Die Quelle der Textdatei.
* @param charset Das zu verwendene {@code Charset}.
* @return Eine Liste mit den Zeilen der Textdatei.
*/
public static List<String> loadLines( String source, Charset charset ) {
try( BufferedReader reader = ResourceStreamProvider.getReader(source, charset) ) {
@@ -52,10 +78,28 @@ public final class FileLoader {
}
}
/**
* Lädt den Inhalt der angegebenen Textdatei vollständig in einen String.
* <p>
* Als {@link Charset} wird {@link #UTF8} verwendet.
*
* @param source Eine Quelle für die Textdatei (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkressource)
* @return Der Inhalt der Textdatei.
*/
public static String loadText( String source ) {
return loadText(source, UTF8);
}
/**
* Lädt den Inhalt der angegebenen Textdatei mit dem angegebenen
* {@code Charset} vollständig in einen String.
*
* @param source Eine Quelle für die Textdatei (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkressource)
* @param charset Der {@code Charset} der Textdatei.
* @return Der Inhalt der Textdatei.
*/
public static String loadText( String source, Charset charset ) {
try( BufferedReader reader = ResourceStreamProvider.getReader(source, charset) ) {
StringBuilder result = new StringBuilder();
@@ -73,15 +117,16 @@ public final class FileLoader {
}
/**
* Lädt die Daten aus einer CSV Datei in ein zweidimensionales
* Lädt die Daten aus einer CSV-Datei in ein zweidimensionales
* String-Array.
* <p>
* Der Aufruf entspricht dem Aufruf von
* Der Aufruf entspricht
* <pre><code>
* FileLoader.loadCsv(source, ',', skipFirst, UTF8);
* </code></pre>
*
* @param source Die Quelle der CSV-Daten.
* @param source Eine Quelle für die CSV-Datei (Absoluter Dateipfad,
* * Dateipfad im Classpath oder Netzwerkressource)
* @param skipFirst Ob die erste Zeile übersprungen werden soll.
* @return Ein Array mit den Daten als {@code String}s.
* @see #loadCsv(String, char, boolean, Charset)
@@ -91,12 +136,12 @@ public final class FileLoader {
}
/**
* Lädt die Daten aus einer CSV Datei in ein zweidimensionales
* Lädt die Daten aus einer CSV-Datei in ein zweidimensionales
* String-Array.
* <p>
* Die Methode ist nicht in der Lage, komplexe CSV-Dateien zu verarbeiten.
* Insbesondere können Inhalte, die das Trennzeichen {@code separator}
* enthalten, nicht korrekt erkannt werden. Das Trennzeichen wird unabhängig
* Insbesondere werden Inhalte, die das Trennzeichen {@code separator}
* enthalten, nicht korrekt erkannt. Das Trennzeichen wird unabhängig
* vom Kontext immer als Zelltrenner erkannt. (Im Normalfall kann das
* Trennzeichen durch die Verwendung doppelter Anführungszeichen in der Art
* {@code Inhalt,"Inhalt, der Komma enthält",Inhalt} maskiert werden.)

View File

@@ -13,39 +13,38 @@ import java.nio.file.Files;
import java.nio.file.Path;
/**
* Helferklasse, um {@link InputStream}s für Resourcen zu erhalten.
* Helferklasse, um {@link InputStream}s für Ressourcen zu erhalten.
*/
@SuppressWarnings("unused")
public class ResourceStreamProvider {
/**
* Ermittelt zur angegebenen Quelle einen passenden {@link URL} (<em>Unified
* Resource Locator</em>). Eine passende Datei-Resource wird wie folgt
* Resource Locator</em>). Eine passende Datei-Ressource wird wie folgt
* ermittelt:
* <ol>
* <li>Ist {@code source} eine existierende Datei
* ({@code new File(source}.isFile() == true})?</li>
* <li>Ist {@code source} ein relativer Pfad im Projekt ({@code getResource(source) != null})?.</li>
* <li>Ist {@code source} ein relativer Pfad im Projekt ({@code getResource(source) != null})?</li>
* <li>Ist {@code source} im Classpath enthalten ({@code getClassLoader().getResource(source) != null})?</li>
* <li>Ansonten erstellt ein {@link URL}-Objekt.</li>
* <li>Ansonsten erstelle ein {@link URL}-Objekt.</li>
* </ol>
* <p>
* Ein {@code URL} für die erste gefundene Resource wird zurückgegeben.
* Auftretende Exceptions
* werden als {@link IOException} geworfen.
* <p>
* Bei einer Exception werden die folgenden Quellen nicht mehr abgefragt.
* Auftretende Exceptions werden als {@link IOException} geworfen.
* Bei einer Exception werden die nachfolgenden Quellen nicht mehr abgefragt.
* Eine {@link java.net.MalformedURLException} beim Konstruieren des {@code URL}
* zu einer Datei verhindert daher, dass noch im Classpath gesucht wird.
*
* @param source Eine Quelle für die Resource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource)
* @return Ein {@code InputStream} für die Resource
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkressource)
* @return Ein {@code InputStream} für die Ressource
* @throws NullPointerException Falls {@code source} {@code null} ist.
* @throws IllegalArgumentException Falls {@code source} ein leerer String
* ist.
* @throws IOException Geworfen beim Erzeugen einer URL zu
* einer bestehenden Resource.
* einer bestehenden Ressource.
*/
public static URL getResourceURL( String source ) throws NullPointerException, IllegalArgumentException, IOException {
Validator.requireNotNull(source, "Resource source may not be null");
@@ -66,12 +65,12 @@ public class ResourceStreamProvider {
}
/**
* Sucht eine zur angegebenen Quelle passende Resource und öffnet einen
* Sucht eine zur angegebenen Quelle passende Ressource und öffnet einen
* passenden {@link InputStream}. Die konkrete Art des Streams hängt davon
* ab, welche Art an Resource gefunden wird:
* ab, welche Art an Ressource gefunden wird:
* <ol>
* <li>Ist {@code source} eine existierende Datei
* {@code new File(source}.isFile() == true}, dann wird ein
* {@code new File(source).isFile() == true}, dann wird ein
* {@link FileInputStream} erstellt.</li>
* <li>Ist {@code source} ein relativer Pfad im Projekt, wird ein passender
* Stream mit {@link Class#getResourceAsStream(String)} geöffnet.</li>
@@ -81,35 +80,44 @@ public class ResourceStreamProvider {
* {@link URL#openStream() Netwerkstream} geöffnet.</li>
* </ol>
* <p>
* Die Möglichen Resourcen werden in der gelisteten Reihenfolge durchprobiert
* Die Möglichen Ressourcen werden in der gelisteten Reihenfolge durchprobiert
* und der erste gefundene Stream zurückgegeben. Auftretende Exceptions
* werden als {@link IOException} geworfen. Das bedeutet, falls für {@code source}
* keine gültige Resource gefunden werden kann, wird am Ende die
* keine gültige Ressource gefunden werden kann, wird am Ende die
* von {@link URL#openStream()} erzeugte {@code IOException} geworfen.
* <p>
* Bei einer Exception werden die folgenden Quellen nicht mehr abgefragt.
* Bei einer Exception werden die nachfolgenden Quellen nicht mehr abgefragt.
* Eine {@link SecurityException} beim Öffnen des {@code FileInputStream}
* (zum Beispiel, weil auf eine existierende Datei keine Leserechte bestehen)
* verhindert daher, dass noch im Classpath gesucht wird.
*
* @param source Eine Quelle für die Resource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource)
* @return Ein {@code InputStream} für die Resource
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource).
* @return Ein {@code InputStream} für die Ressource.
* @throws NullPointerException Falls {@code source} {@code null} ist.
* @throws IllegalArgumentException Falls {@code source} ein leerer String
* ist.
* @throws IOException Geworfen beim Öffnen des Streams zu
* einer bestehenden Resource oder falls
* keine passende Resource gefunden wurde.
* einer bestehenden Ressource oder falls
* keine passende Ressource gefunden
* wurde.
*/
public static InputStream getInputStream( String source ) throws NullPointerException, IllegalArgumentException, IOException {
return getResourceURL(source).openStream();
}
/**
* @param source
* @return
* @throws IOException
* Sucht eine zur angegebenen Quelle passende Ressource und öffnet einen
* passenden {@link OutputStream}.
* <p>
* Es wird davon ausgegangen, dass die Quelle auf eine Datei verweist, auf
* die Schreibrechte bestehen. Ist dies nicht der Fall, wird eine
* {@link IOException} geworfen.
*
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath).
* @return {@code OutputStream} für die Ressource.
* @throws IOException Falls die Quelle kein gültiges Ziel beschreibt.
*/
public static OutputStream getOutputStream( String source ) throws IOException {
try {
@@ -119,22 +127,83 @@ public class ResourceStreamProvider {
}
}
/**
* Sucht eine zur angegebenen Quelle passende Ressource und öffnet einen
* {@link BufferedReader}.
* <p>
* Die Suche erfolgt, wie bei {@link #getInputStream(String)} beschrieben.
* <p>
* Als {@link Charset} wird {@link StandardCharsets#UTF_8 UTF-8} verwendet.
*
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource).
* @return Ein {@code BufferedReader} für die Quelle.
* @throws IOException Falls die Quelle nicht exisitert oder nicht geöffnet
* werden kann.
* @see #getInputStream(String)
*/
public static BufferedReader getReader( String source ) throws IOException {
return getReader(source, StandardCharsets.UTF_8);
}
/**
* Sucht eine zur angegebenen Quelle passende Ressource und öffnet einen
* {@link BufferedReader} mit dem angegebenen Charset.
* <p>
* Die Suche erfolgt wie bei {@link #getInputStream(String)} beschrieben.
*
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource).
* @param charset Der zu verwendende Charset.
* @return Ein {@code BufferedReader} für die Quelle.
* @throws IOException Falls die Quelle nicht exisitert oder nicht geöffnet
* werden kann.
* @see #getInputStream(String)
*/
public static BufferedReader getReader( String source, Charset charset ) throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream(source), charset.newDecoder()));
}
/**
* Sucht eine zur angegebenen Quelle passende Datei und öffnet einen
* {@link BufferedWriter}.
* <p>
* Die Suche erfolgt wie bei {@link #getOutputStream(String)} beschrieben.
* <p>
* Als {@link Charset} wird {@link StandardCharsets#UTF_8 UTF-8} verwendet.
*
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource).
* @return Ein {@code BufferedWriter} für die Quelle.
* @throws IOException Falls die Quelle nicht exisitert oder nicht geöffnet
* werden kann.
* @see #getOutputStream(String)
*/
public static BufferedWriter getWriter( String source ) throws IOException {
return getWriter(source, StandardCharsets.UTF_8);
}
/**
* Sucht eine zur angegebenen Quelle passende Datei und öffnet einen
* {@link BufferedWriter}.
* <p>
* Die Suche erfolgt wie bei {@link #getOutputStream(String)} beschrieben.
* <p>
* Als {@link Charset} wird {@link StandardCharsets#UTF_8 UTF-8} verwendet.
*
* @param source Eine Quelle für die Ressource (Absoluter Dateipfad,
* Dateipfad im Classpath oder Netzwerkresource).
* @return Ein {@code BufferedWriter} für die Quelle.
* @param charset Der zu verwendende Charset.
* @throws IOException Falls die Quelle nicht exisitert oder nicht geöffnet
* werden kann.
* @see #getOutputStream(String)
*/
public static BufferedWriter getWriter( String source, Charset charset ) throws IOException {
return new BufferedWriter(new OutputStreamWriter(getOutputStream(source), charset.newEncoder()));
}
// Privater C'tor
private ResourceStreamProvider() {
}