diff --git a/core/src/main/java/org/libreoffice/lots/config/SyntaxErrorException.java b/core/src/main/java/org/libreoffice/lots/config/SyntaxErrorException.java index d6f795ad2..d4d202a34 100644 --- a/core/src/main/java/org/libreoffice/lots/config/SyntaxErrorException.java +++ b/core/src/main/java/org/libreoffice/lots/config/SyntaxErrorException.java @@ -23,13 +23,13 @@ package org.libreoffice.lots.config; /** - * Signalisiert einen Fehler in einer zu parsenden Zeichenfolge + * Indicates an error in a string to be parsed. * @author Matthias Benkmann (D-III-ITD 5.1) */ public class SyntaxErrorException extends Exception { /** - * keine Ahnung was das soll, aber es macht Eclipse glücklich. + * I have no idea what this is for, but it makes Eclipse happy. */ private static final long serialVersionUID = 7215084024054862356L; public SyntaxErrorException() {super();} diff --git a/core/src/main/java/org/libreoffice/lots/db/Dataset.java b/core/src/main/java/org/libreoffice/lots/db/Dataset.java index bee0f316e..7c0d27956 100644 --- a/core/src/main/java/org/libreoffice/lots/db/Dataset.java +++ b/core/src/main/java/org/libreoffice/lots/db/Dataset.java @@ -23,23 +23,22 @@ package org.libreoffice.lots.db; /** - * Interface für Datensätze einer Tabelle. + * Interface for records of a table. */ public interface Dataset { /** - * Liefert den Wert des Datensatzes aus der Spalte columnName (null falls nicht belegt). + * Returns the value of the record from the column columnName (null if not filled). * * @throws ColumnNotFoundException - * falls die Spalte nicht existiert. Man beachte, dass dies eine Eigenschaft des - * Datenbankschemas ist und nichts damit zu tun hat, ob der Wert des Datensatzes in der - * entsprechenden Spalte gesetzt ist. + * If the column does not exist. Note that this is a property of the database schema + * and has nothing to do with whether the value of the record is set in the + * corresponding column. */ public String get(String columnName) throws ColumnNotFoundException; /** - * Liefert den Schlüsselwert dieses Datensatzes. Dieser sollte den Datensatz in seiner Datenbank - * eindeutig identifizieren muss es aber nicht. + * Returns the key value of this record. This should uniquely identify the record in its database, but it's not mandatory. */ public String getKey(); } diff --git a/core/src/main/java/org/libreoffice/lots/db/DatasetNotFoundException.java b/core/src/main/java/org/libreoffice/lots/db/DatasetNotFoundException.java index 49a252e34..a77a5703a 100644 --- a/core/src/main/java/org/libreoffice/lots/db/DatasetNotFoundException.java +++ b/core/src/main/java/org/libreoffice/lots/db/DatasetNotFoundException.java @@ -23,9 +23,9 @@ package org.libreoffice.lots.db; /** - * Wird geworfen, falls kein passender Datensatz gefunden wurde und - * die Möglichkeit, eine leere Ergebnisliste zurückzugeben nicht - * existiert. + * Thrown if no matching record was found and + * the possibility to return an empty result list does not + * exists. * @author Matthias Benkmann (D-III-ITD 5.1) */ public class DatasetNotFoundException extends Exception diff --git a/core/src/main/java/org/libreoffice/lots/db/Datasource.java b/core/src/main/java/org/libreoffice/lots/db/Datasource.java index 5fa347e6b..5e3721e88 100644 --- a/core/src/main/java/org/libreoffice/lots/db/Datasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/Datasource.java @@ -34,26 +34,24 @@ import org.slf4j.LoggerFactory; /** - * Interface für Datenquellen, die der DJ verwalten kann. ACHTUNG! Die Konstruktoren dieser Klasse - * dürfen keine potentiell lange blockierenden Aktionen (zum Beispiel Netzverbindung herstellen) - * ausführen. Sie dürfen auch nicht versagen, falls irgendeine Rahmenbedingung nicht gegeben ist, - * die nur für Zugriffe auf die Datensätze relevant ist (z.B. Verbindung zum LDAP-Server). Der - * Konstruktor darf (und muss) nur dann versagen, wenn es nicht möglich ist, die Datenquelle in - * einen Zustand zu bringen, in dem sie die Methoden ausführen kann, die unabhängig von den - * Datensätzen sind. Am wichtigsten sind hier die Methoden zur Abfrage des Schemas. Für die - * Methoden, die auf Datensätze zugreifen gilt, dass ihr Versagen aufgrund von Rahmenbedingungen - * (z.B. kein Netz) nicht dazu führen darf, dass das Datenquellen-Objekt in einen unbrauchbaren - * Zustand gerät. Wo immer sinnvoll sollte es möglich sein, eine Operation zu einem späteren - * Zeitpunkt zu wiederholen, wenn die Rahmenbedingungen sich geändert haben, und dann sollte die - * Operation gelingen. Dies bedeutet insbesondere, dass Verbindungsaufbau zu Servern wo nötig - * jeweils neu versucht wird und nicht nur einmalig im Konstruktor. In diesem Zusammenhang sei - * darauf hingewiesen, dass Verbindungen explizit mit close() beendet werden sollten (typischerweise - * in einem finally() Block, damit der Befehl auch im Ausnahmefall ausgeführt wird), weil die - * Garbage Collection von Java dies evtl. sehr spät tut.
- *
- * Argumente gegen Datasource-Typ "override": - (korrekte) Suche nur schwierig und ineffizient zu - * implementieren - würde vermutlich dazu führen, dass Daten im LDAP schlechter gepflegt werden, - * weil es einfacher ist, einen Override einzuführen + * Interface for data sources that the DJ can manage. CAUTION! The constructors of this class must not perform + * potentially long-blocking actions (e.g., establishing a network connection). + * They must not fail if any preconditions are not met, which are only relevant for + * accessing the records (e.g., connection to the LDAP server). + * The constructor should (and must) only fail if it's not possible to bring the data source + * into a state where it can execute methods that are independent of the records. + * Most importantly, this includes methods for querying the schema. + * For methods that access records, their failure due to conditions (e.g., no network) + * must not render the data source object unusable. Wherever possible, + * it should be possible to retry an operation at a later time if the conditions have changed, + * and the operation should succeed then. This particularly means that connection establishment to servers, + * where necessary, should be retried as needed and not just once in the constructor. + * In this context, it should be noted that connections should be explicitly + * closed using close() (typically in a finally() block to ensure it's executed even in exceptional cases) + * because Java's Garbage Collection may do this very late.
+ *
Arguments against the "override" data source type: - (correct) search implementation + * would be difficult and inefficient - would likely result in poorer data maintenance in + * LDAP because it's easier to introduce an override */ public abstract class Datasource { @@ -63,14 +61,14 @@ public abstract class Datasource private static Long datasourceTimeout = null; /** - * Liefert eine Liste, die die Titel aller Spalten der Datenquelle enthält. + * Returns a list containing the titles of all columns in the data source. */ public abstract List getSchema(); /** - * Liefert alle Datensätze, deren Schlüssel in der Collection keys enthalten sind. Man beachte, - * dass die Eindeutigkeit von Schlüsseln nur eine Empfehlung darstellt. Die Anzahl der - * zurückgelieferten Datensätze kann also die Anzahl der übergebenen Schlüssel übersteigen. + * Returns all records whose keys are included in the collection 'keys.' + * Please note that the uniqueness of keys is only a recommendation. + * The number of returned records may exceed the number of provided keys. * * @param keys * Keys to search against. @@ -79,9 +77,9 @@ public abstract class Datasource public abstract QueryResults getDatasetsByKey(Collection keys); /** - * Liefert alle Datensätze, die alle Bedingungen von query (Liste von {@link QueryPart}s) - * erfüllen. Ist query leer, werden keine Datensätze zurückgeliefert. Enthält query Bedingungen - * über Spalten, die die Datenbank nicht hat, werden keine Datensätze zurückgeliefert. + * Returns all records that satisfy all conditions specified in the 'query' (a list of {@link QueryPart}s). + * If 'query' is empty, no records are returned. If 'query' contains conditions on columns that the database + * does not have, no records are returned. * * @param query * Query to search against the main datasource. @@ -90,14 +88,14 @@ public abstract class Datasource public abstract QueryResults find(List query); /** - * Liefert eine implementierungsabhängige Teilmenge der Datensätze der Datenquelle. Wenn möglich - * sollte die Datenquelle hier all ihre Datensätze zurückliefern oder zumindest soviele wie - * möglich. Es ist jedoch auch erlaubt, dass hier gar keine Datensätze zurückgeliefert werden. + * Returns an implementation-dependent subset of records from the data source. + * Ideally, the data source should return all of its records here, or at least as many as possible. + * However, it is also permissible for no records to be returned in this context. */ public abstract QueryResults getContents(); /** - * Liefert den Namen dieser Datenquelle. + * Returns the name of this data source. */ public abstract String getName(); diff --git a/core/src/main/java/org/libreoffice/lots/db/Datasources.java b/core/src/main/java/org/libreoffice/lots/db/Datasources.java index e8e231fcc..27cd962b7 100644 --- a/core/src/main/java/org/libreoffice/lots/db/Datasources.java +++ b/core/src/main/java/org/libreoffice/lots/db/Datasources.java @@ -119,9 +119,9 @@ public static Map getDatasources() { LOGGER.error("Data source {} of type {} could not be initialized", name, type); /* - * Falls schon eine alte Datenquelle name registriert ist, entferne diese Registrierung. - * Ansonsten würde mit der vorher registrierten Datenquelle weitergearbeitet, was seltsame - * Effekte zur Folge hätte die schwierig nachzuvollziehen sind. + * If an old data source with the name 'name' is already registered, remove that registration. + * Otherwise, continuing with the previously registered data source + * would result in strange and hard-to-trace effects. */ } diff --git a/core/src/main/java/org/libreoffice/lots/db/DummyDatasourceWithMessagebox.java b/core/src/main/java/org/libreoffice/lots/db/DummyDatasourceWithMessagebox.java index e16de49b7..3af914672 100644 --- a/core/src/main/java/org/libreoffice/lots/db/DummyDatasourceWithMessagebox.java +++ b/core/src/main/java/org/libreoffice/lots/db/DummyDatasourceWithMessagebox.java @@ -27,10 +27,9 @@ import java.util.Vector; /** - * Eine Dummy-Datenquelle, die im Schema keine Datensätze enthält und als QueryResult - * bei getDatasetsByKey den String "<key>" zurück liefert. - * - * verwendet im noConfig Modus. + * A dummy data source that does not contain any records in the schema and + * returns the string <key> as a QueryResult + * when used in 'noConfig' mode * * @author Matthias Benkmann (D-III-ITD 5.1) */ diff --git a/core/src/main/java/org/libreoffice/lots/db/EmptyDatasource.java b/core/src/main/java/org/libreoffice/lots/db/EmptyDatasource.java index 4760e79af..1f90a8768 100644 --- a/core/src/main/java/org/libreoffice/lots/db/EmptyDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/EmptyDatasource.java @@ -27,7 +27,7 @@ import java.util.Vector; /** - * Eine Datenquelle, die keine Datensätze enthält. + * A data source that contains no records. * * @author Matthias Benkmann (D-III-ITD 5.1) */ diff --git a/core/src/main/java/org/libreoffice/lots/db/FunkyDatasource.java b/core/src/main/java/org/libreoffice/lots/db/FunkyDatasource.java index 07d14ed1b..29b3b750a 100644 --- a/core/src/main/java/org/libreoffice/lots/db/FunkyDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/FunkyDatasource.java @@ -36,10 +36,9 @@ import org.libreoffice.lots.util.L; /** - * Datasource, die mit WollMux-Funktionen berechnete Spalten ermöglicht. ACHTUNG! - * Diese Datasource verhält sich bei Suchanfragen nicht entsprechend dem normalen - * Verhalten einer Datasource, da sie immer auf den Originaldaten sucht, jedoch - * transformierte Datensätze zurückliefert. + * Data source that enables columns calculated with WollMux functions. + * CAUTION! This data source does not behave in search queries according to the normal behavior of a data source, + * as it always searches the original data but returns transformed records. * * @author Matthias Benkmann (D-III-ITD-D101) */ @@ -54,14 +53,12 @@ public class FunkyDatasource extends Datasource private ColumnTransformer columnTransformer; /** - * Erzeugt eine neue FunkyDatasource. + * Creates a new FunkyDatasource. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser UnionDatasource - * bereits vollständig instanziierten Datenquellen. + * Contains all data sources that were fully instantiated up to the point of defining this UnionDatasource. * @param sourceDesc - * der "Datenquelle"-Knoten, der die Beschreibung dieser UnionDatasource - * enthält. + * The 'data source' node containing the description of this UnionDatasource. */ public FunkyDatasource(Map nameToDatasource, ConfigThingy sourceDesc) throws ConfigurationErrorException diff --git a/core/src/main/java/org/libreoffice/lots/db/LDAPDatasource.java b/core/src/main/java/org/libreoffice/lots/db/LDAPDatasource.java index 58b386be6..62d6323c9 100644 --- a/core/src/main/java/org/libreoffice/lots/db/LDAPDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/LDAPDatasource.java @@ -57,7 +57,7 @@ import org.slf4j.LoggerFactory; /** - * Datasource für Zugriff auf ein LDAP-Verzeichnis + * Data source for accessing an LDAP directory. * * @author Max Meier (D-III-ITD 5.1) */ @@ -76,77 +76,76 @@ public class LDAPDatasource extends Datasource private String objectClass; - /** properties für die Verbindung zum LDAP-Server */ + /** Properties for the connection to the LDAP server. */ private Properties properties = new Properties(); - /** Separator zur Schluesselerzeugung aus mehreren Schluesselwerten */ + /** Separator for generating keys from multiple key values. */ private static final String SEPARATOR = "&:=&:%"; /** - * Trennt den ersten Teil des Schlüssels, der den Pfaden mit Level 0 entspricht vom Rest des - * Schlüssels + * Splits the first part of the key, corresponding to paths with Level 0, from the rest of the key. */ private static final String KEY_SEPARATOR_0_NON_0_RE = "==%§%=="; - /** Map von query-Strings auf LDAP-Attributnamen */ + /** Map of query strings to LDAP attribute names */ private Map columnDefinitions = new HashMap<>(); /** Key-Attribute (LDAP) (Strings). */ private List keyAttributes = new ArrayList<>(); /** - * Was für Arten von Pfaden kommen als Schlüsselspalten vor (ABSOLUTE_ONLY, RELATIVE_ONLY, + * What types of paths are present as key columns? (ABSOLUTE_ONLY, RELATIVE_ONLY, * ABSOLUTE_AND_RELATIVE). */ - private int keyStatus; // 0:= nur absolute Attribute, 1:= absolute und + private int keyStatus; // 0:= only absolute attributes, 1:= absolute and - // relative Attribute, 2:= nur relative Attribute - /** nur Attributpfade der Form 0:*. */ + // relative Attribute, 2:= only relative Attribute + /** Only attribute paths of the form 0:*. */ private static final int ABSOLUTE_ONLY = 0; - /** nur Attributpfade der Form num:* wobei num nicht 0 ist. */ + /** Only attribute paths of the form num:*, where num is not 0. */ private static final int RELATIVE_ONLY = 2; - /** Sowohl Attributpfade der Form 0:* als auch der Form num:* mit num ungleich 0. */ + /** Both attribute paths of the form 0:* and the form num:* with num not equal to 0. */ private static final int ABSOLUTE_AND_RELATIVE = 1; - /** regex für erlaubte Bezeichner */ + /** Regex for allowed identifiers */ private static final Pattern SPALTENNAME = Pattern.compile("^[a-zA-Z_][a-zA-Z_0-9]*$"); /** - * Regex zum Checken der Syntax von BASE_DN. TOD0: Sicher zu restriktiv! + * Regex for checking the syntax of BASE_DN. TODO: Likely too restrictive! */ private static final Pattern BASEDN_RE = Pattern .compile("^[a-zA-Z]+=[a-zA-ZäÄöÖüÜß \\\\()-]+(,[a-zA-Z]+=[a-zA-ZäÄöÖüÜß \\\\()-]+)*$"); /** - * Regex zum Checken der Syntax von LDAP-Attributsbezeichnern. TOD0: Sicher zu restriktiv! + * Regex for checking the syntax of LDAP attribute identifiers. TODO: Likely too restrictive! */ private static final Pattern ATTRIBUTE_RE = Pattern.compile("^[a-zA-Z]+$"); /** - * Regex zum Checken, ob ein Schlüssel für die LDAP-Datasource legal ist. + * Regex to check if a key is legal for the LDAP data source. */ private static final Pattern KEY_RE = Pattern.compile("^(\\(&(\\([^()=]+[^()]*\\))+\\))?" + KEY_SEPARATOR_0_NON_0_RE + "([a-zA-Z_][a-zA-Z0-9_]*=.*" + SEPARATOR + ")?$"); /** - * temporärer cache für relative Attribute (wird bei jeder neuen Suche neu angelegt) + * temporary cache for relative attributes (is created with every new search) */ private Map attributeCache = new HashMap<>(); /** - * Erzeugt eine neue LDAPDatasource. + * Creates a new LDAP Datasource. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser LDAPDatasource bereits - * vollständig instanziierten Datenquellen (zur Zeit nicht verwendet). + * Contains all data sources that were fully instantiated up to the + * point of defining this LDAPDatasource (not currently used). * @param sourceDesc - * der "Datenquelle"-Knoten, der die Beschreibung dieser LDAPDatasource enthält. + * The 'data source' node containing the description of this LDAPDatasource.. * @param context - * der Kontext relativ zu dem URLs aufgelöst werden sollen (zur Zeit nicht verwendet). + * The context relative to which URLs should be resolved (not currently used).. * @throws ConfigurationErrorException - * falls in der Definition in sourceDesc ein Fehler ist. + * If there is an error in the definition in sourceDesc. */ @SuppressWarnings("squid:S2068") public LDAPDatasource(Map nameToDatasource, ConfigThingy sourceDesc, @@ -208,10 +207,10 @@ public LDAPDatasource(Map nameToDatasource, ConfigThingy sou schema = new ArrayList<>(); - // iteriere über alle Spalten-Relationen + // Iterate over all column relationships for (ConfigThingy spaltenDesc : spalten) { - // iteriere über eine Spalten-Relation + // Iterate over a column relationship for (ConfigThingy spalteDesc : spaltenDesc) { String spalte = parseConfig(spalteDesc, "DB_COLUMN", @@ -273,7 +272,7 @@ public LDAPDatasource(Map nameToDatasource, ConfigThingy sou try { - // der letzte definierte Schluessel wird verwendet + // The last defined key is used. keySpalten = keys.getLastChild(); } catch (NodeNotFoundException e) { @@ -289,17 +288,17 @@ public LDAPDatasource(Map nameToDatasource, ConfigThingy sou errorMessage() + L.m("No Key column specified.")); } - boolean onlyRelative = true; // true, falls kein Attributpfad der Form 0:* - boolean onlyAbsolute = true; // true, falls nur Attributspfade der Form 0:* + boolean onlyRelative = true; // True if there are no attribute paths of the form 0:* + boolean onlyAbsolute = true; // True if there are only attribute paths of the form 0:* - // speichere die Schluesselattribute + // Save the key attributes. while (keyIterator.hasNext()) { String currentName = keyIterator.next().toString(); ColumnDefinition currentKeyLDAPAttribute = columnDefinitions.get(currentName); - // ist Schluesselattribut vorhanden? + // Is key attribute present? if (currentKeyLDAPAttribute == null) throw new ConfigurationErrorException(L.m( "Column \"{0}\" was not defined in the schema and therefore it cannot be used as a key column.", @@ -329,7 +328,7 @@ public LDAPDatasource(Map nameToDatasource, ConfigThingy sou } } - /** Setzt die timeout-Properties. */ + /** Set the timeout properties. */ private void setTimeout(long timeout) { properties.setProperty("com.sun.jndi.ldap.connect.timeout", Long.toString(timeout)); @@ -338,7 +337,7 @@ private void setTimeout(long timeout) } /** - * repräsentiert eine Spaltendefinition + * Represents a column definition * * @author Max Meier (D-III-ITD 5.1) */ @@ -346,20 +345,22 @@ private static class ColumnDefinition { /** - * relativer Pfad: 0 := Attribut befindet sich im selben Knoten negativ := relative Pfadangabe - * "nach oben" vom aktuellen Knoten aus positiv := relative Pfadangabe von der Wurzel aus + * Relative path: + * 0 := Attribute located in the same node + * Negative := relative path specification 'upward' from the current node + * Positive := relative path specification from the root */ int relativePath; /** - * Name der Spalte. + * Name of the column. */ String columnName; - /** Attributname im LDAP */ + /** LDAP attribute name */ String attributeName = null; - /** exklusive objectClass */ + /** Exclusive objectClass */ String columnObjectClass = null; /** line separator */ @@ -433,10 +434,10 @@ public QueryResults getDatasetsByKey(Collection keys) attributeCache.clear(); if (keyStatus == ABSOLUTE_ONLY || keyStatus == ABSOLUTE_AND_RELATIVE) - { // absolute Attribute vorhanden + { // Absolute attributes present. results.addAll(handleAbsoluteKeys(keys)); } else - { // nur relative Attribute + { // Only relative attributes for (String currentKey : keys) { List query = keyToFindQuery(currentKey); @@ -499,8 +500,8 @@ private List handleAbsoluteKeys(Collection keys) } /** - * Speichert eine Liste von (Ldap)Names, die zu einer Suchanfrage über Attribute mit Pfad-Level - * ungleich 0 gehören (alle mit dem selben Level). + * Saves a list of (Ldap)Names that belong to a search query for attributes with a path + * level not equal to 0 (all with the same level). * * @author Max Meier (D-III-ITD 5.1) */ @@ -520,9 +521,8 @@ private static class RelativePaths } /** - * Ein (Ldap)Name und der Pfad-Level für die Suche. Typischerweise ist der Pfad-Level != 0, aber - * ein Level von 0 ist auch möglich (kann bei Bildung der Schnittmenge von positiven und negativen - * Kandidaten entstehen). + * An (Ldap)Name and the path level for the search. Typically, the path level is not equal to 0, + * but a level of 0 is also possible (can arise when intersecting positive and negative candidates). * * @author Max Meier (D-III-ITD 5.1) */ @@ -542,7 +542,7 @@ private static class RelativePath } /** - * Liefert zum Pfadlevel pathLength alle Knoten, die auf die LDAP-Suchanfrage filter passen + * Returns, for the path level 'pathLength,' all nodes that match the LDAP search filter * * @author Max Meier (D-III-ITD 5.1) */ @@ -574,9 +574,9 @@ private RelativePaths getPaths(String filter, int pathLength) String path = preparePath(result.getNameInNamespace()); Name pathName = np.parse(path); /* - * ACHTUNG: hier kann NICHT (pathLength < 0 && (pathName.size()+rootLength > - * abs(pathLength))) getestet werden, denn Minus-Bedingungen betreffen die Nachfahren, hier - * muesste also die Tiefe des tiefsten Nachfahrens ausgewertet werden, die wir nicht kennen. + * CAUTION: here, you CANNOT test (pathLength < 0 && (pathName.size()+rootLength > abs(pathLength))) + * because negative conditions apply to descendants. + * So, you would need to evaluate the depth of the deepest descendant, which we do not know. */ if (pathName.size() + rootSize == pathLength || pathLength < 0) paths.add(pathName); @@ -679,8 +679,8 @@ public QueryResults find(List query) } - // TOD0 evtl. Optimierung: attributeKeys nicht in zufälliger Reihenfolge - // durchgehen + // TODO: Possible optimization: Do not iterate through attributeKeys in a + // random order for (Map.Entry ent : mapNon0PathLevelToSearchFilter.entrySet()) { Integer currentKey = ent.getKey(); @@ -697,9 +697,8 @@ public QueryResults find(List query) } else { /* - * RelativePaths in Liste von RelativePath Objekten umwandeln, da nachher im Merge-Schritt - * eine Liste entstehen soll, in der Pfade verschiedener Stufe gemischt enthalten sein - * können. + * Convert RelativePaths into a list of RelativePath objects because later in the merge step, + * there should be a list that can contain paths of different levels mixed together. */ List negativeSubtreePaths = new ArrayList<>(); for (Name currentName : paths.paths) @@ -712,39 +711,37 @@ public QueryResults find(List query) } /* - * bilde die Schnittmenge aller angegebenen positiv relativen Pfade + * Intersect all specified positively relative paths * - * Dieser Algorithmus vergleicht zwei Listen, die jeweils alle relevanten Pfade eines - * Suchattributs repräsentieren. Zuerst werden die Listen nach der Länge der enthaltenen Pfade - * sortiert, danach wird betrachte, ob für jedes Element der Liste der längeren Pfade ein - * Element aus der Liste der kürzeren Pfade existiert, das ein Prefix des ersten Elements ist. - * Wenn ja, wird das Element in die Liste mergedPositiveSubtreePathLists aufgenommen und somit - * weiter betrachtet, wenn nein, ist die Schnittmengeneigenschaft nicht gegeben und der Pfad - * wird verworfen. + * This algorithm compares two lists, each representing all relevant paths of a search attribute. + * First, the lists are sorted by the length of the contained paths. + * Then, it checks whether for each element in the longer path list, + * there exists an element in the shorter path list that is a prefix of the first element. + * If yes, the element is added to the mergedPositiveSubtreePathLists and further considered. + * If not, the intersection property is not satisfied, and the path is discarded. */ List mergedPositiveSubtreePathLists = null; - int mergedCurrentSize = 0; // TOD0: Der Name ist Bullshit. Die Variable gibt den - // Level an. okay, size bezieht sicht auf die laenge - // der (Ldap)Names + int mergedCurrentSize = 0; // TODO: The name is nonsense. The variable represents + // Level is okay, 'size' refers to the length + // The (Ldap)Names if (!positiveSubtreePathLists.isEmpty()) /* - * TODO if nach aussen ziehen (evtl. gleich auf Iterator übergehen, siehe todo weiter unten), - * damit mergedPositiveSubtreePathLists nicht mit null initialisiert werden muss und damit - * beweisbar ist, dass es initialisiert ist + * TODO: Move 'if' to the outside (possibly switch to an iterator as mentioned in the TODO below) + * so that mergedPositiveSubtreePathLists doesn't have to be initialized with null,and it can be proven to be initialized */ { RelativePaths currentSubtreePaths = positiveSubtreePathLists.get(0); /* - * TODO: Hier wird eine Liste von zufälligem Level rausgepickt (entsprechend sortierung von - * attributeMap.keySet(), Wo ist die oben angesprochene Sortierung? + * TODO: Here, a list of random levels is selected (according to the sorting of attributeMap.keySet()). + * Where is the sorting mentioned above? */ mergedPositiveSubtreePathLists = currentSubtreePaths.paths; mergedCurrentSize = currentSubtreePaths.relative; } for (int n = 1; n < positiveSubtreePathLists.size(); n++) // TOD0 Iterator - // verwenden + // Use. { RelativePaths currentSubtreePaths = positiveSubtreePathLists.get(n); @@ -789,9 +786,8 @@ public QueryResults find(List query) * Vergleiche jeweils zwei Listen, die je ein Suchattribut repräsentieren. */ List mergedNegativeList = null; - if (!negativeSubtreePathLists.isEmpty()) // TOD0 if nach oben ziehen, um - // mergedNegativeList nicht mit null - // initialisieren zu müssen + if (!negativeSubtreePathLists.isEmpty()) // TODO: Move 'if' upwards to avoid initializing + // mergedNegativeList with null. { mergedNegativeList = negativeSubtreePathLists.get(0); } @@ -801,7 +797,7 @@ public QueryResults find(List query) List newMergedNegativeList = new ArrayList<>(); /* - * alle Objekte von currentList haben die selbe Stufe. + * All objects in currentList have the same level. */ List currentList = negativeSubtreePathLists.get(n); @@ -810,16 +806,16 @@ public QueryResults find(List query) RelativePath currentPath = mergedNegativeList.get(m); /* - * Suche zu currentPath in der currentList einen Pfad, der eine Aussage über eine Teilmenge - * oder eine Obermenge der Nachkommen von currentPath macht, die potentielle Ergebnisse - * sind. Beispiel + * Search in currentList for a path related to currentPath that makes a statement about a + * subset or a superset of the descendants of currentPath, which are potential results. + * For example */ - // A1:-2 Hier ist A1 ein Knoten der auf eine Suchbedingung mit Level -2 - // passt, d.h. - // / | von dem Enkelkinder potentielle Ergebnisse sind. - // D B:-1 Bei B sind Kinder potentielle Ergebnisse. Die Enkelkinder von A1 - // sind eine - // | | \ Obermenge der Kinder von B. + // A1:-2 Here, A1 is a node that corresponds to a search condition with level -2 + // matches, meaning. + // / | potential results come from its grandchildren. + // D B:-1 BAt B, children are potential results. The grandchildren of A1 + // are a + // | | \ superset of the children of B. // | | \ // E C1 C2 /* @@ -868,7 +864,7 @@ public QueryResults find(List query) } /* - * bilde die Schnittmenge aus den positiv und negativ relativen Listen + * Intersection of the positively and negatively relative lists */ List mergedNegativeSubtreePaths; if (mergedPositiveSubtreePathLists != null && mergedNegativeList != null) @@ -891,16 +887,16 @@ public QueryResults find(List query) && currentPath.name.size() - currentPath.relative >= currentName.size()) { /* - * Wir bilden einen neuen RelativePath mit dem Namen des positiven (currentName), der - * tiefer im Baum liegt und einem (negativen) Level, der die selbe Nachfahrenebene - * selektiert wie der Level des negativen (currentPath). Achtung: Es ist möglich, dass - * der neu-gebildete Level 0 ist. + * We create a new RelativePath with the name of the positive (currentName), + * which is deeper in the tree, and a (negative) level that selects the same descendant + * level as the level of the negative (currentPath). + * Note: It's possible that the newly formed level is 0. */ RelativePath newPath = new RelativePath( currentName.size() - currentPath.name.size() + currentPath.relative, currentName); mergedNegativeSubtreePaths.add(newPath); - // kein break weil mit dem selben negativen currentPath mehrere - // Schnitte möglich sind. + // No break because the same negative currentPath can match multiple + // Intersections are possible. } } else @@ -920,8 +916,8 @@ public QueryResults find(List query) mergedNegativeSubtreePaths = mergedNegativeList; } - // TOD0: die Listen sollten nie null sein (siehe vorherige TODOs) - // entsprechend muss hier auf isEmpty() getestet werden + // TODO: The lists should never be null (see previous TODOs) + // Accordingly, isEmpty() should be tested here if (searchFilter.length() == 0 && mergedPositiveSubtreePathLists == null && mergedNegativeSubtreePaths == null) { @@ -931,11 +927,11 @@ public QueryResults find(List query) List currentResultList = new ArrayList<>(); /* - * TOD0: besser insgesamt auf havePositiveConstraints und haveNegativeConstrainst Booleans - * umstellen, anstatt die size zu überprüfen. Könnte zum Irrtum verleiten, dass hier - * mergedNegativeSubtreePaths getestet werden sollte, was aber nicht stimmt, da wenn die - * mergedListe leer ist, eine leere Ergebnisliste geliefert werden muss, wenn es positive - * einschränkungen gibt. + * TODO: Better to switch to using havePositiveConstraints and + * haveNegativeConstraints Booleans instead of checking the size. + * Checking the size could lead to the misconception that mergedNegativeSubtreePaths + * should be tested here, which is not the case. If the merged list is empty but there + * are positive constraints, an empty result list must be returned. */ if (negativeSubtreePathLists.isEmpty()) { @@ -957,7 +953,7 @@ public QueryResults find(List query) } - // allgemeine Suche + // General Search for (String subTree : positiveSubtreeStrings) { @@ -979,12 +975,12 @@ public QueryResults find(List query) } } else - { // Breitensuche ausgehend von den Knoten der mergedNegativeSubtreePaths + { // Breadth-first search starting from the nodes of mergedNegativeSubtreePaths for (RelativePath currentRelativePath : mergedNegativeSubtreePaths) { int depth = -currentRelativePath.relative; - // ACHTUNG: depth kann 0 sein. Siehe Kommentar bei Bildung des Schnitts aus - // negativen und positiven Pfaden. + // CAUTION: depth can be 0. See comment when forming the intersection + // negative and positive paths. Name currentName = currentRelativePath.name; String currentPath = currentName.toString(); @@ -1017,8 +1013,8 @@ public QueryResults find(List query) } /** - * Escaping nach RFC 2254 Abschnitt 4. Sternderl werden nicht escapet, weil sie ihre normale - * Sternerl-Bedeutung beibehalten sollen. + * Escaping according to RFC 2254 Section 4. Asterisks are not escaped + * because they should retain their normal asterisk meaning */ private String ldapEscape(String value) { @@ -1038,7 +1034,7 @@ public String getName() } /** - * generiert einen Schluessel aus einem geordneten(!) Vector der Schluesselwerte + * Generates a key from an ordered vector of key values. * * @param values * @return @@ -1055,9 +1051,9 @@ private String generateKey(Map data) keyColumns.add(colDef); } - // Spalten alphabetisch und nach Pfad-Level sortieren, um einen - // wohldefinierten Schlüssel zu erhalten, der unabhängig von der Ordnung - // der Map ist. + // Sort columns alphabetically and by path level to create a + // well-defined key that is independent of the order, resulting in a consistent key + // of the map. Collections.sort(keyColumns, (o1, o2) -> { ColumnDefinition colDef1 = o1; ColumnDefinition colDef2 = o2; @@ -1154,7 +1150,7 @@ public boolean equals(Object other) } /** - * vervollständigt SearchResults um Daten aus dem Verzeichnis und gibt ein Dataset zurück + * Completes SearchResults with data from the directory and returns a dataset * * @param searchResult * @param endTime @@ -1180,11 +1176,10 @@ private Dataset getDataset(SearchResult searchResult) ctx = new InitialLdapContext(properties, null); NameParser nameParser = ctx.getNameParser(""); pathName = nameParser.parse(tempPath); - rootName = nameParser.parse(baseDN); // TOD0: Das ist eine Konstante, nur - // einmal berechnen (ausser, dass dies - // nur mit funktionierender - // Netzanbindung moeglich ist). Testen - // mit rausgezogenem Netzkabel + rootName = nameParser.parse(baseDN); // TOD0: This is a constant, only + // calculated only once (except that this + // only with a functioning + // network connection is possible). Testing with the network cable unplugged } catch (NamingException e) { @@ -1210,7 +1205,7 @@ private Dataset getDataset(SearchResult searchResult) } catch (NamingException | NullPointerException e) { LOGGER.trace("", e); - // do nothing (Attributwert nicht vorhanden und bleibt somit 'null') + // do nothing (Attribute value is not present and remains 'null'.) } } else @@ -1222,12 +1217,12 @@ private Dataset getDataset(SearchResult searchResult) { if (relativePath < 0) - { // Pfad relativ zum aktuellen Element + { // Path relative to the current element attributePath.addAll(pathName.getPrefix(pathName.size() + relativePath)); } else - { // relativePath > 0, Pfad relativ zur Wurzel + { // relativePath > 0, path relative to the root attributePath.addAll(pathName.getPrefix(relativePath - rootName.size())); } @@ -1254,7 +1249,7 @@ private Dataset getDataset(SearchResult searchResult) } catch (NamingException | NullPointerException | IndexOutOfBoundsException e) { - // do nothing (Attributwert nicht vorhanden und bleibt somit 'null') + // do nothing (Attribute value is not present and remains 'null') LOGGER.trace("", e); } } @@ -1276,19 +1271,18 @@ private Dataset getDataset(SearchResult searchResult) } /** - * Sucht im Teilbaum path + BASE_DN nach Knoten, auf die Suchkriterium filter passt. + * Searches in the subtree path + BASE_DN for nodes that match the search criteria filter. * * @param path - * der Pfad des Startknotens. Wird mit BASE_DN konkateniert. + * The path of the starting node. Concatenated with BASE_DN * @param filter - * der Suchfilter. + * The search filter. * @param searchScope - * SearchControls.SUBTREE_SCOPE, SearchControls.OBJECT_SCOPE oder - * SearchControls.ONELEVEL_SCOPE, um anzugeben wo gesucht werden soll. + * SearchControls.SUBTREE_SCOPE, SearchControls.OBJECT_SCOPE or + * SearchControls.ONELEVEL_SCOPE, to specify where to search. * @param onlyObjectClass - * falls true, werden nur Knoten zurückgeliefert, deren objectClass {@link #objectClass} - * entspricht. - * @return die Suchergebnisse + * If true, only nodes matching the objectClass {@link #objectClass} will be returned. + * @return The search results * @author Max Meier (D-III-ITD 5.1) * @throws NamingException * @@ -1309,9 +1303,7 @@ private NamingEnumeration searchLDAP(String path, String filter, i filter = "(&(objectClass=" + objectClass + ")" + filter + ")"; } else { - filter = "(&(objectClass=" + "*" + ")" + filter + ")"; // TOD0 das - // objectClass=* ist - // doch überflüssig + filter = "(&(objectClass=" + "*" + ")" + filter + ")"; // TODO: The objectClass=* is unnecessary } Optional> result = Optional.empty(); @@ -1351,11 +1343,11 @@ private NamingEnumeration searchLDAP(String path, String filter, i } /** - * Durchsucht die Nachfahren des durch path + BASE_DN bezeichneten Knotens mit Abstand level zu - * diesem Knoten nach Knoten, die auf die Suchanfrage filter passen. Es werden nur Objekte mit - * objectClass = {@link #objectClass} geliefert. + * Searches the descendants of the node designated by path + BASE_DN with a distance of 'level' + * from this node for nodes that match the search criteria filter. + * Only objects with objectClass = {@link #objectClass} are returned * - * @return eine List von {@link SearchResult}s. + * @return A list of {@link SearchResult}s * @author Max Meier (D-III-ITD 5.1) * */ @@ -1427,19 +1419,17 @@ private List searchLDAPLevel(String path, String filter, int level } /** - * Entferne umschliessende Doublequotes aus path falls vorhanden. [Folgende Erklärung stimmt - * eventuell nicht mehr, seit von getName() auf getNameInNamespace() umgestellt wurde. Eventuell - * kann das ganze Doublequote-Killen entfallen] Dies muss gemacht werden, da das Zeichen '/' in - * LDAP Pfadkomponenten erlaubt ist, im JNDI jedoch als Komponententrenner verwendet wird. - * Deswegen werden Pfade, die '/' enthalten von .getName() in Anführungszeichen gesetzt und können - * deshalb nicht mehr geparsed werden.] - * - * Nach dem Entfernen der Doublequotes wird geschaut ob path auf {@link #baseDN} endet (ist - * normalerweise der Fall) und falls ja wird dieses Suffix weggeschnitten. - * - * [Folgendes ist mit der Umstellung auf getNameInNamespace() eventuell auch überholt: TOD0 Ich - * bin mir nicht sicher, ob hier nicht noch mehr zu tun ist. Was ist z.B. mit enthaltenen - * Doublequotes? Kann das passieren? Wie werden die escapet?] + * Remove enclosing double quotes from path if present. + * [The following explanation may not be accurate anymore since the switch from getName() + * to getNameInNamespace() was made. It may be possible to eliminate the entire double quote removal process.] + * This needs to be done because the character '/' is allowed in LDAP path components, + * but is used as a component separator in JNDI. Therefore, paths containing '/' are enclosed in double quotes + * by .getName() and cannot be parsed anymore. + After removing the double quotes, it is checked whether path ends with {@link #baseDN} + (usually the case), and if so, this suffix is removed. + [The following may also be outdated with the switch to getNameInNamespace(): + TODO I'm not sure if there's more to be done here. + What about contained double quotes? Can that happen? How are they escaped?] * * @author Max Meier, Matthias Benkmann (D-III-ITD 5.1) * diff --git a/core/src/main/java/org/libreoffice/lots/db/NoBackingStoreException.java b/core/src/main/java/org/libreoffice/lots/db/NoBackingStoreException.java index 4791f5fc1..2b55bbac5 100644 --- a/core/src/main/java/org/libreoffice/lots/db/NoBackingStoreException.java +++ b/core/src/main/java/org/libreoffice/lots/db/NoBackingStoreException.java @@ -23,8 +23,7 @@ package org.libreoffice.lots.db; /** - * Wird geworfen beim Versuch, auf eine Spalte zuzugreifen, die - * nicht existiert. + * Thrown when attempting to access a column that does not exist. * * @author Matthias Benkmann (D-III-ITD 5.1) */ diff --git a/core/src/main/java/org/libreoffice/lots/db/OOoDatasource.java b/core/src/main/java/org/libreoffice/lots/db/OOoDatasource.java index 5004c3218..53c912f67 100644 --- a/core/src/main/java/org/libreoffice/lots/db/OOoDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/OOoDatasource.java @@ -55,7 +55,7 @@ import org.libreoffice.lots.util.L; /** - * Stellt eine OOo-Datenquelle als WollMux-Datenquelle zur Verfügung. + * Provides an OpenOffice.org data source as a WollMux data source. */ public class OOoDatasource extends Datasource { @@ -63,121 +63,116 @@ public class OOoDatasource extends Datasource private static final Logger LOGGER = LoggerFactory.getLogger(OOoDatasource.class); /** - * Maximale Zeit in Sekunden, die die Datenquelle für die Verbindungsaufnahme mit - * der Datenbank brauchen darf. + * Maximum time in seconds that the data source is allowed to take for connecting to the database. */ private static final int LOGIN_TIMEOUT = 5; /** - * Konstante für {@link #sqlSyntax}, die angibt, dass SQL Queries in Oracle-Syntax - * abgesetzt werden sollen. + * Constant for {@link #sqlSyntax} indicating that SQL queries should be executed in Oracle syntax. */ private static final int SQL_SYNTAX_ANSI = 0; /** - * Konstante für {@link #sqlSyntax}, die angibt, dass SQL Queries in Oracle-Syntax - * abgesetzt werden sollen. + * Constant for {@link #sqlSyntax} indicating that SQL queries should be executed in Oracle syntax. */ private static final int SQL_SYNTAX_ORACLE = 1; /** - * Konstante für {@link #sqlSyntax}, die angibt, dass SQL Queries in MySQL-Syntax - * abgesetzt werden sollen. + * Constant for {@link #sqlSyntax} indicating that SQL queries should be executed in MySQL syntax. */ private static final int SQL_SYNTAX_MYSQL = 2; /** - * Konstante für {@link #sqlSyntax}, die angibt, dass SQL Queries in PervasiveSQL-Syntax - * abgesetzt werden sollen. + * Constant for {@link #sqlSyntax} indicating that SQL queries should be executed in PervasiveSQL syntax. */ private static final int SQL_SYNTAX_PERVASIVESQL = 3; /** - * Welche Syntax soll verwendet werden. + * Which syntax should be used? * - * Default ist Oracle-Syntax. + * The default is Oracle syntax * * o *** ANSI ********* ::= 2 consecutive double quote characters * - * (Lexical Elements, 135 Foundation) Ein delimited Identifier ist ein von "..." umschlossener - * Identifier. Im Identifier enthaltene Doublequotes werden durch ersetzt. + * (Lexical Elements, 135 Foundation)A delimited Identifier is an Identifier enclosed in '...' double quotes. + * Double quotes contained within the Identifier are replaced by . * (Lexical Elements, 134 Foundation) * * ::= (2 consecutive quote characters) (Lexical elements, 143 - * Foundation) In einem werden einzelne s durch - * ersetzt. (Lexical elements, 143 Foundation) + * Foundation) In a individual s by + * replaced. (Lexical elements, 143 Foundation) * - * o**** Datensätze zu vorgegebener Schlüsselliste finden ********* + * o**** Find records based on a given key list ********* * * SELECT * FROM "" WHERE (""='' AND ""='' AND ...) OR (...) OR * ...; * - * In und sind Doublequotes durch ersetzt. + * In and Doublequotes are replaced by . * - * In sind Quotes durch ersetzt. + * In Quotes are replaced by . * - * o ***** Datensätze finden, die bestimmte Kriterien erfüllen ******** + * o ***** Find records that meet certain criteria ******** * - * 8.5 (385 Foundation) Der String hinter ESCAPE muss genau ein Zeichen lang - * sein. Ansonsten gibt es eine Exception (387 Foundation, 8.5 General Rules 3b)) _ und % sowie - * das ESCAPE-Zeichen selbst müssen im String-Ausdruck hinter LIKE escapet werden (durch - * Voranstellen des Escape-Zeichens). Andere Zeichen dürfen nicht escapet werden. + * 8.5 (385 Foundation)The string behind ESCAPE must be exactly one character long. + * Otherwise, an exception is thrown (387 Foundation, 8.5 General Rules 3b)) _ and % as well as the + * ESCAPE character itself must be escaped in the string expression behind + * LIKE (by prepending the escape character). Other characters must not be escaped. * * SELECT * FROM "" WHERE (lower("") LIKE lower('') ESCAPE '|') AND (...) AND - * ...; In und sind Doublequotes durch ersetzt. In - * sind "_", "%" und "|" ersetzt durch "|_", "|%" und "||". + * ...; In und Doublequotes are replaced by . In + * are "_", "%" and "|" replaced by "|_", "|%" und "||". ***** - * Alle Datensätze auslesen ****** + * Read all records ****** * - * SELECT * FROM ""; In sind Doublequotes durch ersetzt. + * SELECT * FROM ""; In Doublequotes is replaced by . **** - * Oracle ***** Wie ANSI MySQL ******* Wie ANSI, aber mit lcase() statt lower() PervasiveSQL - * ******* Wie ANSI, aber rechts vom LIKE dürfen nur einfache Konstanten (also kein lower oder - * lcase) stehen. Außerdem wird "DATENBANK.TABELLE" nicht unterstützt. Nur "DATENBANK"."TABELLE", - * DATENBANK."TABELLE" oder "TABELLE". + * Oracle ***** Like ANSI MySQL ******* Like ANSI, but with lcase() instead of lower() for PervasiveSQL. + * ******* Like ANSI, but to the right of LIKE, only simple constants are allowed (no lower or lcase). + * Additionally, "DATABASE.TABLE" is not supported. + * Only "DATABASE"."TABLE", DATABASE."TABLE", or "TABLE"." is allowed. */ private int sqlSyntax = SQL_SYNTAX_ANSI; /** - * Der Name dieser Datenquelle. + * The name of this data source. */ private String datasourceName; /** - * Der Name der OpenOffice-Datenquelle. + * The name of the OpenOffice data source. */ private String oooDatasourceName; /** - * Der Name der Tabelle in der OpenOffice-Datenquelle. + * The name of the table in the OpenOffice data source. */ private String oooTableName; /** - * Das Schema dieser Datenquelle. + * The schema of this data source. */ private List schema; /** - * Die Namen der Spalten, die den Primärschlüssel bilden. + * The names of the columns that form the primary key. */ private String[] keyColumns; /** - * Benutzername für den Login bei der Datenbank. + * Username for logging in to the database. */ private String userName = ""; private static final String SQL_SELECT_COMMAND = "SELECT * FROM "; /** - * Passwort für den Login bei der Datenbank. + * Password for logging in to the database. */ @SuppressWarnings("squid:S2068") private String password = ""; /** - * Wie {@link #OOoDatasource(Map, ConfigThingy, boolean)}, wobei noKey==false übergeben wird. + * How {@link #OOoDatasource(Map, ConfigThingy, boolean)}, where noKey==false is passed. */ public OOoDatasource(Map nameToDatasource, ConfigThingy sourceDesc) { @@ -185,28 +180,23 @@ public OOoDatasource(Map nameToDatasource, ConfigThingy sour } /** - * Erzeugt eine neue OOoDatasource. Wenn kein SQL_SYNTAX Parameter in ConfigThingy - * gesetzt ist, wird 'mysql' als Standard verwendet. + * Creates a new OOoDatasource. If no SQL_SYNTAX parameter is set in ConfigThingy, 'mysql' is used as the default. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser OOoDatasource - * bereits vollständig instanziierten Datenquellen (zur Zeit nicht - * verwendet). + * Contains all data sources that were fully instantiated up to the + * time of defining this OOoDatasource (currently not used). * @param sourceDesc - * der "DataSource"-Knoten, der die Beschreibung dieser OOoDatasource - * enthält. + * The 'DataSource' node containing the description of this OOoDatasource. * @param noKey - * Falls true, so wird immer die erste Spalte als Schlüsselspalte - * verwendet. Diese Option sollte nur verwendet werden, wenn keine - * Operationen getätigt werden sollen, die den Schlüssel verwenden. + * If true, the first column is always used as the key column. + * This option should only be used if no operations are to be performed that use the key. * @throws ConfigurationErrorException - * falls in der Definition in sourceDesc ein Fehler ist. Falls sourceDesc - * keinen Schema-Unterabschnitt aufweist, wird versucht, das Schema von - * der Datenquelle selbst zu bekommen. Tritt dabei ein Fehler auf wird - * ebenfalls diese Exception geworfen. *Keine* Exception wird geworfen, - * wenn die Spalten des Schema-Abschnitts nicht in der realen Datenbank - * vorhanden sind. In diesem Fall werden die entsprechenden Spalten als - * leer behandelt. TESTED + * If there is an error in the definition in sourceDesc. + * If sourceDesc does not have a schema subsection, + * an attempt is made to obtain the schema from the data source itself. + * If an error occurs in this process, this exception is also thrown. + * No exception is thrown if the columns of the schema section do not exist in the real database. + * In this case, the corresponding columns are treated as empty. TESTED */ public OOoDatasource(Map nameToDatasource, ConfigThingy sourceDesc, boolean noKey) @@ -266,7 +256,7 @@ else if ("pervasivesql".equalsIgnoreCase(sqlSyntaxStr)) } } else - parseKey(schluesselConf); // Test ob kein Schluessel vorhanden siehe weiter + parseKey(schluesselConf); // Test if no key is present, see further. // unten } else @@ -280,7 +270,7 @@ else if ("pervasivesql".equalsIgnoreCase(sqlSyntaxStr)) XConnection conn = ds.getConnection(userName, password); /* - * Laut IDL-Doku zu "View" müssen hier auch die Views enthalten sein. + * According to the IDL documentation for 'View,' views must also be included here */ UnoDictionary tables = UnoDictionary .create(UNO.XTablesSupplier(conn).getTables(), XColumnsSupplier.class); @@ -327,10 +317,10 @@ else if ("pervasivesql".equalsIgnoreCase(sqlSyntaxStr)) ConfigThingy schluesselConf = sourceDesc.query("Schluessel"); if (schluesselConf.count() != 0) { - // Test ob kein Schluessel vorhanden siehe weiter unten + // Test if no key is present, see further below parseKey(schluesselConf); } else - { // Schlüssel von Datenbank abfragen. + { // Query keys from the database. try { XKeysSupplier keysSupp = UNO.XKeysSupplier(table); @@ -345,7 +335,7 @@ else if ("pervasivesql".equalsIgnoreCase(sqlSyntaxStr)) throw new ConfigurationErrorException(L.m("Data source \"{0}\": No key columns defined." + " Automatic determination of key column not possible.", datasourceName), x); } - // Test ob kein Schluessel vorhanden siehe weiter unten + // Test if no key is present, see further below } } } @@ -367,11 +357,9 @@ else if ("pervasivesql".equalsIgnoreCase(sqlSyntaxStr)) } /** - * Parst das erste Kind von conf (das existieren und ein Schluessel-Knoten sein - * muss) und setzt {@link #keyColumns} entsprechend. + * Parses the first child of conf (which must exist and be a key node) and sets {@link #keyColumns} accordingly. * @throws ConfigurationErrorException - * falls eine Schluessel-Spalte nicht im {@link #schema} ist. Es wird - * *keine* Exception geworfen, wenn der Schluessel-Abschnitt leer ist. + * If a key column is not in the {@link #schema}. No exception is thrown if the key section is empty. * TESTED */ private void parseKey(ConfigThingy conf) @@ -467,12 +455,10 @@ public QueryResults find(List query) buffy.append(" LIKE "); if (SQL_SYNTAX_PERVASIVESQL == sqlSyntax) { - // Rechts vom LIKE können nur einfache Konstanten und keine Funktionen wie - // lcase oder lower genutzt werden. Daher wird hier über die Java Methode - // toLowerCase der zu suchende String in Kleinbuchstaben umgewandelt. - // Die Inhalte der zu durchsuchenden Spalte können wiederum mit lcase/lower - // behandelt werden. Somit ist sichergestellt, dass der durchsuchende und der zu - // suchende String nur Kleinbuchstaben enthält. + // To the right of LIKE, only simple constants and no functions like lcase or lower can be used. + // Therefore, the search string is converted to lowercase using the Java method toLowerCase. + // The contents of the column to be searched can in turn be treated with lcase/lower. + // This ensures that the searching and the search string both contain only lowercase letters. buffy.append(sqlLiteral(sqlSearchPattern(part.getSearchString())).toLowerCase()); } else { buffy.append(sqlLower()); @@ -495,7 +481,7 @@ public QueryResults getContents() } /** - * Setzt die SQL-Anfrage query an die Datenbank ab und liefert die Resultate. + * Executes the SQL query query against the database and returns the results. */ private QueryResults sqlQuery(String query) { @@ -529,12 +515,11 @@ private QueryResults sqlQuery(String query) UnoProperty.setProperty(results, UnoProperty.ACTIVE_CONNECTION, conn); /* - * EscapeProcessing == false bedeutet, dass OOo die Query nicht selbst anfassen - * darf, sondern direkt an die Datenbank weiterleiten soll. Wird dies verwendet - * ist das Ergebnis (derzeit) immer read-only, da OOo keine Updates von - * Statements durchführen kann, die es nicht geparst hat. Siehe Kommentar zu - * http://qa.openoffice.org/issues/show_bug.cgi?id=78522 Entspricht dem Button - * SQL mit grünem Haken (SQL-Kommando direkt ausführen) im Base-Abfrageentwurf. + * EscapeProcessing == false means that OOo should not manipulate the query + * itself but should pass it directly to the database. When this is used, + * the result (currently) is always read-only, as OOo cannot perform updates on + * statements it has not parsed. See comment at http://qa.openoffice.org/issues/show_bug.cgi?id=78522. + * Equivalent to the button 'Execute SQL Command Directly' in the Base Query Design. */ UnoProperty.setProperty(results, UnoProperty.ESCAPE_PROCESSING, Boolean.FALSE); @@ -592,9 +577,9 @@ private QueryResults sqlQuery(String query) } /** - * Liefert eine Abbildung der Spaltennamen aus {@link #schema} auf Integer-Indizes, - * die die Spaltennummern für XRow(results)::getString() sind. Falls eine Spalte - * nicht existiert, ist ihr index <= 0. + * Returns a mapping of column names from schema to integer indices, + * which are the column numbers for XRow(results)::getString(). + * If a column does not exist, its index is <= 0. */ private Map getColumnMapping(XResultSet results) { @@ -619,8 +604,7 @@ private Map getColumnMapping(XResultSet results) } /** - * Liefert abhängig von {@link #sqlSyntax} den "richtigen" Namen der - * lower()-Funktion. + * Returns the 'correct' name of the lower() function depending on sqlSyntax. */ private String sqlLower() { @@ -632,11 +616,10 @@ private String sqlLower() } /** - * Liefert str zurück, als String-Literal vorbereitet für das Einfügen in - * SQL-Statements. + * Returns str as a string literal prepared for insertion into SQL statements. * * @param str - * beginnt und endet immer mit einem Apostroph. + * The string literal returned by prepareForSqlInsert always begins and ends with a single apostrophe ('). */ private static String sqlLiteral(String str) { @@ -644,16 +627,15 @@ private static String sqlLiteral(String str) } /** - * Liefert str zurück, als Identifier-Name vorbereitet für das Einfügen in - * SQL-Statements. + * Returns str as an identifier name prepared for insertion into SQL statements. * * @param str - * beginnt und endet immer mit einem Doublequote. + * begins and ends with a double quote. */ private String sqlIdentifier(String str) { if (SQL_SYNTAX_PERVASIVESQL == sqlSyntax && str.contains( "." )) { - // PervasiveSQL unterstützt "DATENBANK.TABELLE" nicht, wird somit in "TABELLE" geändert + // PervasiveSQL does not support 'DATABASE.TABLE', thus it is changed to 'TABLE' int dot = str.indexOf( '.' ) + 1; str = str.substring( dot ); } @@ -661,8 +643,7 @@ private String sqlIdentifier(String str) } /** - * Ersetzt das * Wildcard so dass ein SQL-Suchmuster entsteht und escapet Zeichen, - * die für SQL eine Bedeutung haben mit "|". + * Replace the * wildcard so that an SQL search pattern is created and escape characters that have meaning in SQL with '|'. */ private static String sqlSearchPattern(String str) { @@ -689,10 +670,10 @@ public OOoDataset(Map data) } /** - * Setzt aus den Werten der Schlüsselspalten den Schlüssel zusammen. + * Assembles the key from the values of the key columns. * * @param keyCols - * die Namen der Schlüsselspalten + * The names of the key columns */ private void initKey(String[] keyCols) { diff --git a/core/src/main/java/org/libreoffice/lots/db/OverlayDatasource.java b/core/src/main/java/org/libreoffice/lots/db/OverlayDatasource.java index 7b21ff19c..f330d3aa0 100644 --- a/core/src/main/java/org/libreoffice/lots/db/OverlayDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/OverlayDatasource.java @@ -41,22 +41,20 @@ import org.slf4j.LoggerFactory; /** - * Eine Datenquelle, die eine andere Datenquelle um Spalten ergänzt und einzelne Spaltenwerte - * ersetzen kann. Zur Erstellung der Menge der Ergebnisdatensätze wird jeder Datensatz aus SOURCE1 - * genau einmal verwendet und jeder Datensatz aus SOURCE2 beliebig oft (auch keinmal). Unterschiede - * zu einem richtigen Join:
+ * A data source that supplements another data source with columns and can replace individual column values. + * To create the set of result datasets, each record from SOURCE1 is used exactly once, + * and each record from SOURCE2 can be used any number of times, including zero. + * Differences from a proper data source include:
*
- * a) Verhindert, dass eine Person 2 mal auftaucht, nur weil es 2 Einträge mit Verkehrsverbindungen - * für ihre Adresse gibt
- * b) Verhindert, dass eine Person rausfliegt, weil es zu ihrer Adresse keine Verkehrsverbindung - * gibt
- * c) Die Schlüssel der Ergebnisdatensätze bleiben die aus SOURCE1 und werden nicht kombiniert aus - * SOURCE1 und SOURCE2. Das verhindert, dass ein Datensatz bei einer Änderung der Adresse aus der - * lokalen Absenderliste fliegt, weil er beim Cache-Refresh nicht mehr gefunden wird.
+ * a) Prevents a person from appearing twice just because there are two entries with traffic connections for their + * address
+ * b) Prevents a person from being removed because there is no traffic connection to their address
+ * c) The keys of the result records remain those from SOURCE1 and are not combined from SOURCE1 and SOURCE2. + * This prevents a record from being removed from the local sender list when the address is changed during cache refresh, + * because it cannot be found anymore.
*
- * In der Ergebnisdatenquelle sind alle Spalten unter ihren ursprünglichen Namen verfügbar - * (Unterschied zu {@link AttachDatasource}). Konflikte werden über den MODE-Spezifizierer aufgelöst - * (siehe lots.conf Doku).
+ * In the result data source, all columns are available under their original names (difference from AttachDatasource). + * Conflicts are resolved using the MODE specifier (see lots.conf documentation)
* * @author Matthias Benkmann (D-III-ITD-D101) */ @@ -86,8 +84,8 @@ public class OverlayDatasource extends Datasource private String[] match2; /** - * Enthält die Namen aller Spaltennamen für die es ein i gibt, so dass - * Spaltenname,equals(match1[i]) und match1[i],equals(match2[i]). + * Contains the names of all column names for which there is an i such that + * Columnname.equals(match1[i]) and match1[i].equals(match2[i]). */ private Set commonMatchColumns; @@ -102,15 +100,15 @@ public class OverlayDatasource extends Datasource private boolean treatEmptyStringsAsNull; /** - * Erzeugt eine neue OverlayDatasource. + * Creates a new OverlayDatasource. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser OverlayDatasource bereits - * vollständig instanziierten Datenquellen. + * Contains all data sources that have already been fully instantiated + * up to the time of defining this OverlayDatasource. * @param sourceDesc - * der "DataSource"-Knoten, der die Beschreibung dieser OverlayDatasource enthält. + * the 'DataSource' node containing the description of this OverlayDatasource. * @param context - * der Kontext relativ zu dem URLs aufgelöst werden sollen (zur Zeit nicht verwendet). + * the context relative to which URLs should be resolved (currently not used). */ public OverlayDatasource(Map nameToDatasource, ConfigThingy sourceDesc, URL context) @@ -247,10 +245,10 @@ public QueryResults find(List query) { if (schema2.contains(p.getColumnName()) /* - * Wichtige Optimierung: Bedingungen für Spalten, die in beiden Datenquellen vorkommen, - * die geMATCHt werden (commonMatchColumns), dürfen nicht nach queryBoth gesteckt - * werden, da dies im schlechtesten Fall dazu führt, dass (unnötigerweise) der - * ineffizienteste Code-Pfad in dieser Funktion genommen wird. + * Important optimization: Conditions for columns that occur in both data sources, + * which are matched (commonMatchColumns), must not be placed after queryBoth, + * as this in the worst case leads to the (unnecessary) selection + * of the most inefficient code path in this function. */ && !commonMatchColumns.contains(p.getColumnName())) queryBoth.add(p); @@ -263,10 +261,9 @@ public QueryResults find(List query) } /* - * Die OVERLAY-Datenquelle ist normalerweise nur untergeordnet und Spaltenbedingungen dafür - * schränken die Suchergebnisse wenig ein. Deshalb werten wir falls wir mindestens eine - * Bedingung haben, die exklusiv die Hauptdatenquelle betrifft, die Anfrage auf dieser Basis - * aus. + * The OVERLAY data source is usually subordinate, and column conditions for it only slightly + * restrict the search results. Therefore, if we have at least one condition that exclusively + * affects the main data source, we evaluate the query on this basis. */ if (!queryOnly1.isEmpty()) { @@ -279,32 +276,30 @@ public QueryResults find(List query) return overlayColumns(results, DatasetPredicate.makePredicate(restQuery)); } else if (!queryOnly2.isEmpty()) { /* - * in diesem Fall haben wir nur Bedingungen für Spalten, die entweder bei beiden Datenquellen - * vorkommen oder nur in der OVERLAY-Datenquelle. Auf jeden Fall haben wir mindestens eine - * Spaltenbedingung, die nur die OVERLAY-Datenquelle betrifft. Wir führen die Suche mit den - * Bedingungen der OVERLAY-Datenquelle durch, ergänzen dann daraus alle möglichen Datasets und - * Filtern dann nochmal mit den Spaltenbedingungen für die gemeinsamen Spalten. + * In this case, we have conditions only for columns that either exist in both data sources or only + * in the OVERLAY data source. In any case, we have at least one column condition that exclusively + * affects the OVERLAY data source. We perform the search using the conditions of the OVERLAY data source, + * then add all possible datasets from it, and then filter again with the column conditions for the common columns. */ return overlayColumnsReversed(source2.find(queryOnly2), DatasetPredicate.makePredicate(queryBoth)); } else { /* - * An der Abfrage sind nur Spalten beteiligt, die in beiden Datenquellen vorhanden sind. Hier - * wird's kompliziert, weil für jeden Spaltenwert getrennt der Wert jeweils aus der einen oder - * der anderen Datenquelle kommen kann. Deswegen lassen sich weder aus SOURCE noch aus OVERLAY - * Datensätze bestimmen, die definitiv zum Ergebnisraum gehören. Wir müssen also auf Basis - * beider Datenquellen entsprechende Kandidaten bestimmen. Leider entsteht dabei das Problem - * der Duplikatelimination. Da die Schlüssel von Datensätzen nicht zwingend eindeutig sind, - * ist es nicht so leicht, diese durchzuführen. + * Only columns present in both data sources are involved in the query. + * Here it gets complicated because for each column value, the value can come from either + * one or the other data source separately. Therefore, we cannot determine definitively which + * datasets belong to the result space based on either SOURCE or OVERLAY. + * We must determine the appropriate candidates based on both data sources. + * Unfortunately, this creates the problem of duplicate elimination. + * Since the keys of datasets are not necessarily unique, it is not so easy to perform this. */ /* - * Wegen dem Problem, das im Ergebnisdatensatz evtl. Spalte 1 aus SOURCE und Spalte 2 aus - * OVERLAY kommt, können wir nicht nach mehreren Spaltenbedingungen aus queryBoth gleichzeitig - * suchen. Wir müssen uns also eine Spaltenbedingung heraussuchen, nach dieser suchen und dann - * mit einem Filter, der die komplette Suchbedingung aus query testet die Datensätze - * rausfiltern, die tatsächlich die gesuchten sind. + * Due to the problem that in the result dataset, column 1 may come from SOURCE and column 2 from OVERLAY, + * we cannot search for multiple column conditions from queryBoth simultaneously. + * We must select a column condition, search for it, and then filter the datasets + * that actually match the complete search condition from query. */ QueryPart qp = getMostRestrictingQueryPart(queryBoth); @@ -317,17 +312,16 @@ public QueryResults find(List query) QueryResults results2 = overlayColumnsReversed(source2.find(restrictingQuery), predicate); /* - * An dieser Stelle haben wir alle gesuchten Datensätze. Allerdings kann es zwischen results1 - * und results2 Überschneidungen geben. Dies ist das oben angesprochene Duplikat-Problem. Um - * die Duplikate zu eliminieren gehen wir wie folgt vor: + * At this point, we have all the desired records. However, there may be overlaps between results1 and results2. + * This is the aforementioned duplicate problem. + * To eliminate duplicates, we proceed as follows: * - * 1. Alle Datensatzschlüssel bestimmen, die sowohl in results1 als auch in results2 - * vorkommen. + * 1. Determine all record keys that appear in both results1 and results2. * - * 2. Alle Datensätze mit Schlüsseln aus 1. entfernen aus den results Listen + * 2. Remove all records with keys from the first list (results1) from the results lists * - * 3. In einer weiteren Abfrage alle Datensätze mit den Schlüsseln aus 1. bestimmen und - * diejenigen, die die Filterbedingung erfüllen den Ergebnissen wieder hinzufügen. + * 3. In another query, determine all records with keys from the first list and add + * those that meet the filter condition back to the results. */ HashSet results1Keys = new HashSet<>(); for (Dataset ds : results1) @@ -368,9 +362,9 @@ public QueryResults find(List query) } /** - * Versucht, den QueryPart aus query (darf nicht leer sein) zu bestimmen, der den Ergebnisraum - * einer Suchanfrage am meisten einschränkt und liefert diesen zurück. Kriterium hierfür ist die - * Anzahl der Sternchen und die Anzahl der Nicht-Sternchen-Zeichen im Suchstring. + * Tries to determine the QueryPart from the query (which must not be empty) + * that most restricts the result set of a search query and returns it. + * The criteria for this are the number of asterisks and the number of non-asterisk characters in the search string. * * @author Matthias Benkmann (D-III-ITD-D101) * @@ -378,7 +372,7 @@ public QueryResults find(List query) */ private QueryPart getMostRestrictingQueryPart(List query) { - QueryPart best = query.get(0); // Sicherstellen, dass best immer initialisiert + QueryPart best = query.get(0); // Ensure that 'best' is always initialized // ist int bestStarCount = Integer.MAX_VALUE; int bestNonStarCount = -1; @@ -511,7 +505,7 @@ private class ConcatDataset implements Dataset private Dataset dataset2; // kann null sein! /** - * ds1 is always from SOURCE and ds2 from OVERLAY. + * ds1' is always from 'SOURCE' and 'ds2' is from 'OVERLAY. * * @author Matthias Benkmann (D-III-ITD-D101) */ @@ -555,7 +549,7 @@ public String get(String columnName) throws ColumnNotFoundException try { - // ds1 kann null sein in dem Fall wo ds1 == this.ds2 (bei modeSO == false) + // ds1' can be null in the case where 'ds1 == this.ds2' (when 'modeSO == false') if (ds1 == null) { return null; @@ -563,9 +557,9 @@ public String get(String columnName) throws ColumnNotFoundException return ds1.get(columnName); } catch (ColumnNotFoundException x) { - // Die Exception darf nicht weitergeworfen werden, denn die Spalte existiert - // ja im Gesamtschema, wie ganz oben getestet. Wenn wir hier hinkommen, dann - // nur in in dem Fall, dass der Wert in ds2 unbelegt ist. + // The exception should not be thrown further because the column exists in the overall schema, + // as tested at the beginning. If we reach this point, + // it is only in the case that the value in 'ds2' is unset. return null; } } diff --git a/core/src/main/java/org/libreoffice/lots/db/PreferDatasource.java b/core/src/main/java/org/libreoffice/lots/db/PreferDatasource.java index e22208557..391db5894 100644 --- a/core/src/main/java/org/libreoffice/lots/db/PreferDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/PreferDatasource.java @@ -39,12 +39,12 @@ import org.libreoffice.lots.util.L; /** - * Datasource, die Daten einer Datenquelle A von Dateien einer anderen Datenquelle B - * verdecken lässt. Dies funktioniert so, dass Anfragen erst an Datenquelle A - * gestellt werden und dann für alle Ergebnisdatensätze geprüft wird, ob ein - * Datensatz (oder mehrere Datensätze) mit gleichem Schlüssel in Datenquelle B ist. - * Falls dies so ist, werden für diesen Schlüssel nur die Datensätze aus Datenquelle - * B zurückgeliefert. + * Datasource, the data from one data source A from files from another data source B + * can be concealed. The way this works is that queries are only sent to data source A + * are set and then all result data records are checked to see whether a + * Record (or multiple records) with the same key is in data source B. + * If so, only the records from data source are used for this key + * B returned. * * @author Matthias Benkmann (D-III-ITD 5.1) */ @@ -63,17 +63,15 @@ public class PreferDatasource extends Datasource private String name; /** - * Erzeugt eine neue PreferDatasource. + * Creates a new PreferDatasourcee. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser PreferDatasource - * bereits vollständig instanziierten Datenquellen. + * Contains all data sources that have already been fully instantiated + * up to the point of defining this PreferDatasource. * @param sourceDesc - * der "DataSource"-Knoten, der die Beschreibung dieser PreferDatasource - * enthält. + * the "DataSource" node that contains the description of this PreferDatasource. * @param context - * der Kontext relativ zu dem URLs aufgelöst werden sollen (zur Zeit nicht - * verwendet). + * the context in which the URLs should be resolved (not currently used). */ public PreferDatasource(Map nameToDatasource, ConfigThingy sourceDesc, URL context) @@ -94,12 +92,10 @@ public PreferDatasource(Map nameToDatasource, + "Referenced datasource \"{1}\" missing or defined incorrectly", name, source2Name)); /* - * Anmerkung: Die folgende Bedingung ist "unnötig" streng, aber um sie - * aufzuweichen (z.B. Gesamtschema ist immer Schema von bevorzugter Datenquelle) - * wäre es erforderlich, einen Dataset-Wrapper zu implementieren, der dafür - * sorgt, dass alle Datasets, die in QueryResults zurück- geliefert werden das - * selbe Schema haben. Solange dafür keine Notwendigkeit ersichtlich ist, spare - * ich mir diesen Aufwand. + * The following condition is "unnecessarily" strict, but to relax it (e.g., assuming that the overall + * schema is always the schema of the preferred data source), + * it would be necessary to implement a dataset wrapper that ensures that all datasets returned + * in QueryResults have the same schema. As long as there is no apparent need for this, I will save myself this effort. */ List schema1 = source1.getSchema(); List schema2 = source2.getSchema(); @@ -199,10 +195,9 @@ public QueryResultsOverride(QueryResults results, QueryResults overrideResults, } /** - * Datensätze für die ein Korrekturdatensatz vorliegt, dieaber nicht in - * overrideResults auftauchen (weil die Korrektur dafür gesorgt hat, dass die - * Suchbedingung nicht mehr passt) müssen auch mit ihrem Schlüssel auf die - * Denylist. Deswegen müssen wir diese Datensätze suchen. + * Records for which a correction record exists but do not appear in overrideResults + * (because the correction has made the search condition no longer valid) must + * also be added to the denylist with their key. Therefore, we need to search for these records. */ QueryResults denylistResults = override.getDatasetsByKey(keyToCount.keySet()); diff --git a/core/src/main/java/org/libreoffice/lots/db/Query.java b/core/src/main/java/org/libreoffice/lots/db/Query.java index 4219feb74..7714da725 100644 --- a/core/src/main/java/org/libreoffice/lots/db/Query.java +++ b/core/src/main/java/org/libreoffice/lots/db/Query.java @@ -27,25 +27,25 @@ import java.util.Vector; /** - * Speichert den Namen einer Datenquelle sowie eine Suchanfrage darauf. + * Stores the name of a data source and a search query on it. */ public class Query implements Iterable { /** - * Liste von QueryParts, die die eigentliche Query beschreiben. + * List of QueryParts that describe the actual query. */ private List listOfQueryParts; /** - * Der Name der Datenquelle auf der die Suche erfolgen soll. + * The name of the data source to search on. */ private String dbName; /** - * Erzeugt eine neue Query. - * @param dbName der Name die Datenquelle auf der die Suche erfolgen soll. - * @param listOfQueryParts Liste von QueryParts, die die eigentliche Query - * beschreiben. ACHTUNG! Wird als Referenz eingebunden. + * Creates a new query. + * @param dbName the name of the data source on which the search should take place. + * @param listOfQueryParts List of QueryParts that contain the actual query + * Describe. DANGER! Will be included as a reference. */ public Query(String dbName, List listOfQueryParts) { @@ -54,18 +54,18 @@ public Query(String dbName, List listOfQueryParts) } /** - * Liefert den Namen der Datenquelle auf der die Suche erfolgen soll. + * Provides the name of the data source on which the search should take place. */ public String getDatasourceName() {return dbName;} /** - * Iteriert über die QueryParts, die diese Suchanfrage ausmachen. + * Iterates over the QueryParts that make up this query. */ @Override public Iterator iterator() {return listOfQueryParts.iterator();} /** - * Liefert die Liste der QueryParts die diese Suchanfrage definieren. + * Returns the list of QueryParts that define this search query. */ public List getQueryParts() {return new Vector<>(listOfQueryParts);} diff --git a/core/src/main/java/org/libreoffice/lots/db/QueryPart.java b/core/src/main/java/org/libreoffice/lots/db/QueryPart.java index 4a6f5fc12..5e463e402 100644 --- a/core/src/main/java/org/libreoffice/lots/db/QueryPart.java +++ b/core/src/main/java/org/libreoffice/lots/db/QueryPart.java @@ -24,13 +24,11 @@ /** - * Teil einer Datenbankabfrage. Zur Zeit einfach nur ein Spaltenname und ein - * Suchstring. Selektiert werden alle Datensätze, die in der entsprechenden Spalte - * den Suchstring haben. Der Suchstring kann vorne und/oder hinten genau ein - * Sternchen '*' stehen haben, um Präfix/Suffix/Teilstring-Suche zu realisieren. - * Folgen mehrerer Sternchen oder Sternchen in der Mitte des Suchstrings sind - * verboten und produzieren undefiniertes Verhalten. Ebenso verboten ist ein - * Suchstring, der nur Sternchen enthält oder einer der leer ist. + * Part of a database query. Currently, it consists of only a column name and a search string. + * It selects all records that have the search string in the corresponding column. + * The search string can have exactly one asterisk '*' at the beginning and/or at the end to perform prefix/suffix/partial + * string search. Multiple asterisks or asterisks in the middle of the search string are prohibited + * and result in undefined behavior. Also, a search string that consists solely of asterisks or is empty is not allowed. */ public class QueryPart { @@ -51,7 +49,7 @@ public QueryPart(String spaltenName, String suchString) } /** - * Liefert den Name der zu testenden Spalten. + * Returns the name of the columns to be tested. */ public String getColumnName() { @@ -59,7 +57,7 @@ public String getColumnName() } /** - * Liefert den Suchstring auf den getestet werden soll. + * Returns the search string to test for. */ public String getSearchString() { diff --git a/core/src/main/java/org/libreoffice/lots/db/QueryResults.java b/core/src/main/java/org/libreoffice/lots/db/QueryResults.java index dc4417a8d..64707aa40 100644 --- a/core/src/main/java/org/libreoffice/lots/db/QueryResults.java +++ b/core/src/main/java/org/libreoffice/lots/db/QueryResults.java @@ -23,17 +23,17 @@ package org.libreoffice.lots.db; /** - * Ergebnisse einer Datenbankanfrage. + * Results of a database query. */ public interface QueryResults extends Iterable { /** - * Die Anzahl der Ergebnisse. + * The number of results. */ public int size(); /** - * Liefert true, falls es keine Ergebnisse gibt. + * Returns true if there are no results. */ public boolean isEmpty(); } diff --git a/core/src/main/java/org/libreoffice/lots/db/QueryResultsList.java b/core/src/main/java/org/libreoffice/lots/db/QueryResultsList.java index 8e6203fcb..5c5622da7 100644 --- a/core/src/main/java/org/libreoffice/lots/db/QueryResultsList.java +++ b/core/src/main/java/org/libreoffice/lots/db/QueryResultsList.java @@ -27,23 +27,22 @@ import java.util.List; /** - * Eine einfache Klasse um eine Liste als QueryResults zur - * Verfügung zu stellen. + * A simple class to provide a list as QueryResults. * @author Matthias Benkmann (D-III-ITD 5.1) */ public class QueryResultsList implements QueryResults { /** - * Die Liste der Datasets. + * The list of datasets. */ private List data; /** - * Erzeugt eine neue QueryResultsList, die die Elemente enthält - * die iter zurückliefert (müssen Datasets sein!). - * @param count dient der Optimierung und sollte die Anzahl der Elemente - * enthalten, die der Iterator zurückliefern wird. Ist dies nicht bekannt, - * kann 0 übergeben werden. + * Creates a new QueryResultsList containing the items + * the iterator returns (they must be datasets!). + * @param count serves for optimization and should contain the number of elements + * contain the number of elements that the iterator will return. If this is not known, + * 0 can be passed. */ public QueryResultsList(Iterator iter, int count) { @@ -55,8 +54,8 @@ public QueryResultsList(Iterator iter, int count) } /** - * Erzeugt eine neue QueryResultsList aus einer bestehenden Liste. - * Achtung! Die Liste wird nicht kopiert, sondern als Referenz übernommen. + * Creates a new QueryResultsList from an existing list. + * Danger! The list is not copied, but adopted as a reference. */ public QueryResultsList(List datasets) { @@ -67,11 +66,12 @@ public QueryResultsList(List datasets) public int size() { return data.size();} @SuppressWarnings("unchecked") - // Die Typsicherheit kann hier nicht gefährdet sein, da laut - // http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.htm vor - // allem gesichert sein muss, dass kein falscher Typ zur List - // hinzugefügt wird. So etwas ist mit einem Iterator, der nur die Methoden - // hasNext(), next() und remove() kennt, nicht möglich. + // Type safety cannot be compromised here, since according to + // http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.htm + // it must be ensured above all that no wrong type is added to the + // List. + // Such a thing is not possible with an iterator that only knows the methods + // hasNext(), next() and remove(). @Override public Iterator iterator() { diff --git a/core/src/main/java/org/libreoffice/lots/db/QueryResultsSet.java b/core/src/main/java/org/libreoffice/lots/db/QueryResultsSet.java index 2ac31a3d9..af75b60f1 100644 --- a/core/src/main/java/org/libreoffice/lots/db/QueryResultsSet.java +++ b/core/src/main/java/org/libreoffice/lots/db/QueryResultsSet.java @@ -28,25 +28,25 @@ import java.util.List; /** - * Stellt die Vereinigung mehrerer QueryResults dar. + * Represents the union of multiple QueryResults. * - * Dabei werden doppelte Ergebnisse herausgefiltert. Es handelt sich um eine mathematische Vereinigung. + * Duplicate results are filtered out. It is a mathematical union. * @author daniel.sikeler */ public class QueryResultsSet implements QueryResults { /** - * Mathematische Vereinigung der QueryResults. + * Mathematical union of QueryResults. */ private final List results = new ArrayList<>(); /** - * Anhand dieses Comparators wird die Gleichheit zweiter Datasets erkannt. + * This comparator is used to recognize the equality of two datasets. */ private final Comparator comparator; /** - * Erstellt eine leere Menge. - * @param comparator Der Comparator, der beim Hinzufügen für Vergleiche verwendet wird. + * Creates an empty set. + * @param comparator The comparator to use for comparisons when adding. */ public QueryResultsSet(Comparator comparator) { @@ -54,9 +54,9 @@ public QueryResultsSet(Comparator comparator) } /** - * Erstellt eine Ergebnisliste mit den Datensätzen aus queryResults. - * @param comparator Der Comparator, der beim Hinzufügen für Vergleiche verwendet wird. - * @param queryResults Die Liste der neuen Datensätze. + * Creates a results list with the records from queryResults. + * @param comparator The comparator to use for comparisons when adding. + * @param queryResults The list of new records. */ public QueryResultsSet(Comparator comparator, QueryResults queryResults) { @@ -65,8 +65,8 @@ public QueryResultsSet(Comparator comparator, QueryResults queryResults } /** - * Fügt einen neuen Datensatz hinzu, solange er noch nicht enthalten ist. - * @param dataset Der neue Datensatz. + * Adds a new record as long as it is not already included. + * @param dataset The new record. */ public void add(Dataset dataset) { @@ -86,8 +86,8 @@ public void add(Dataset dataset) } /** - * Fügt alle Datensätze der Liste hinzu, solange sie noch nicht enthalten sind. - * @param queryResults Liste mit neuen Datensätzen. + * Adds all records to the list as long as they are not already included. + * @param queryResults List of new records. */ public void addAll(QueryResults queryResults) { diff --git a/core/src/main/java/org/libreoffice/lots/db/QueryResultsWithSchema.java b/core/src/main/java/org/libreoffice/lots/db/QueryResultsWithSchema.java index 6f4884d28..73249ae45 100644 --- a/core/src/main/java/org/libreoffice/lots/db/QueryResultsWithSchema.java +++ b/core/src/main/java/org/libreoffice/lots/db/QueryResultsWithSchema.java @@ -29,8 +29,7 @@ import java.util.Set; /** - * Ein Container für Ergebnisse einer Datenbankafrage zusammen mit dem zugehörigen - * Schema. + * A container for results of a database query along with the associated schema. */ public class QueryResultsWithSchema implements QueryResults { @@ -48,8 +47,8 @@ public QueryResultsWithSchema() } /** - * Erzeugt ein neues QueryResultsWithSchema, das den Inhalt von res und das Schema - * schema zusammenfasst. ACHTUNG! res und schema werden als Referenzen übernommen. + * Creates a new QueryResultsWithSchema that combines the contents of res and the schema. + * WARNING! res and schema are taken as references. */ public QueryResultsWithSchema(QueryResults res, List schema) { diff --git a/core/src/main/java/org/libreoffice/lots/db/RAMDatasource.java b/core/src/main/java/org/libreoffice/lots/db/RAMDatasource.java index 5a4c755e0..133f334e1 100644 --- a/core/src/main/java/org/libreoffice/lots/db/RAMDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/RAMDatasource.java @@ -30,35 +30,34 @@ import java.util.function.Predicate; /** - * Oberklasse für Datasources, die ihre Daten vollständig im Speicher halten + * Superclass for data sources that keep their data entirely in memory */ public class RAMDatasource extends Datasource { /** - * Das Schema dieser Datenquelle. + * The schema of this data source. */ private List schema; /** - * Liste aller Datasets, die in dieser Datasource gespeichert sind. + * List of all datasets stored in this datasource. */ private List data; /** - * Der Name dieser Datenquelle. + * The name of this data source. */ private String name; /** - * Erzeugt eine neue RAMDatasource mit Namen name. data und schema werden direkt als Referenz - * eingebunden, nicht kopiert. + * Creates a new RAMDatasource with the name 'name'. 'data' and 'schema' are included as references, not copied. * * @param name - * der Name der Datenquelle + * the name of the data source * @param schema - * das Schema der Datenquelle + * the schema of the data source * @param data - * die Datensätze der Datenquelle + * the data source records */ public RAMDatasource(String name, List schema, List data) { @@ -66,17 +65,16 @@ public RAMDatasource(String name, List schema, List data) } /** - * Erzeugt eine uninitialisierte RAMDatasource. Eine abgeleitete Klasse, die diesen Konstruktor - * verwendet sollte init() aufrufen, um die nötigen Initialisierungen zu erledigen. + * Creates an uninitialized RAMDatasource. A derived class that uses this constructor should call 'init()' + * to perform the necessary initializations. */ protected RAMDatasource() { } /** - * Führt die Initialisierungsaktionen des Konstruktors mit den gleichen Parametern aus. Diese - * Methode sollte von abgeleiteten Klassen verwendet werden, wenn sie den Konstruktor ohne - * Argumente verwenden. + * Performs the initialization actions of the constructor with the same parameters. + * This method should be used by derived classes when they use the constructor without arguments. */ protected void init(String name, List schema, List data) { diff --git a/core/src/main/java/org/libreoffice/lots/db/SchemaDatasource.java b/core/src/main/java/org/libreoffice/lots/db/SchemaDatasource.java index a23007453..3dcfcfa06 100644 --- a/core/src/main/java/org/libreoffice/lots/db/SchemaDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/SchemaDatasource.java @@ -40,8 +40,7 @@ import org.slf4j.LoggerFactory; /** - * Datenquelle, die die Daten einer existierenden Datenquelle mit geänderten Spalten - * zur Verfügung stellt. + * Data source that provides data from an existing data source with modified columns. * * @author Matthias Benkmann (D-III-ITD 5.1) */ @@ -65,17 +64,15 @@ public class SchemaDatasource extends Datasource private Map mapNewToOld; /** - * Erzeugt eine neue SchemaDatasource. + * Creates a new SchemaDatasource. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser SchemaDatasource - * bereits vollständig instanziierten Datenquellen. + * contains all data sources that have already been fully instantiated + * up to the point of defining this SchemaDatasource. * @param sourceDesc - * der "DataSource"-Knoten, der die Beschreibung dieser SchemaDatasource - * enthält. + * the "DataSource" node containing the description of this SchemaDatasource. * @param context - * der Kontext relativ zu dem URLs aufgelöst werden sollen (zur Zeit nicht - * verwendet). + * the context relative to which URLs should be resolved (currently not used). */ public SchemaDatasource(Map nameToDatasource, ConfigThingy sourceDesc, URL context) @@ -97,10 +94,9 @@ public SchemaDatasource(Map nameToDatasource, renameColumn(sourceDesc.query("RENAME"), columnsToDrop, columnsToAdd); /** - * Für alle hinzugefügten Spalten, die weder in der Originaldatenbank existieren - * noch durch einen RENAME auf eine Spalte der Originaldatenbank abgebildet - * werden, füge ein Pseudomapping auf EMPTY_COLUMN hinzu, damit - * RenameDataset.get() weiss, dass es für die Spalte null liefern soll. + * For all added columns that do not exist in the original database + * and are not mapped to a column in the original database through a RENAME, + * add a pseudomapping to EMPTY_COLUMN so that RenameDataset.get() knows to return null for the column. */ for (String spalte : columnsToAdd) { @@ -210,12 +206,12 @@ public QueryResults find(List query) QueryPart p = iter.next(); String spalte = p.getColumnName(); - if (!schema.contains(spalte)) // dieser Test ist nicht redundant wegen DROPs + if (!schema.contains(spalte)) // this test is not redundant because of DROPs return new QueryResultsList(new Vector(0)); String alteSpalte = mapNewToOld.get(spalte); - if (alteSpalte == /* nicht equals()!!!! */EMPTY_COLUMN) + if (alteSpalte == /* not equals()!!!! */EMPTY_COLUMN) return new QueryResultsList(new Vector(0)); if (alteSpalte != null) @@ -254,14 +250,14 @@ public RenameDataset(Dataset ds) @Override public String get(String columnName) throws ColumnNotFoundException { - // dieser Test ist nicht redundant wegen DROPs + // this test is not redundant because of DROPs if (!schema.contains(columnName)) throw new ColumnNotFoundException(L.m("Column \"{0}\" does not exist!", columnName)); String alteSpalte = mapNewToOld.get(columnName); - if (alteSpalte == /* nicht equals()!!!! */EMPTY_COLUMN) { + if (alteSpalte == /* not equals()!!!! */EMPTY_COLUMN) { return null; } diff --git a/core/src/main/java/org/libreoffice/lots/db/Search.java b/core/src/main/java/org/libreoffice/lots/db/Search.java index 0358edcad..aef39ad73 100644 --- a/core/src/main/java/org/libreoffice/lots/db/Search.java +++ b/core/src/main/java/org/libreoffice/lots/db/Search.java @@ -32,7 +32,7 @@ import org.libreoffice.lots.config.ConfigThingy; /** - * Diese Klasse stellt Methoden zur Verfügung um in Datenquellen Suchen durchzuführen. + * This class provides methods to perform searches in data sources. */ public class Search { @@ -43,19 +43,19 @@ private Search() } /** - * Führt die übergebene Suchanfrage gemäß der übergebenen Suchstrategie aus und liefert die - * Ergebnisse in einem {@link QueryResults}-Objekt zurück. Falls einer der übergebenen Parameter - * null ist oder falls der queryString leer ist, wird null - * zurückgeliefert. + * Executes the given search query according to the given search strategy and returns the + * results in one {@link QueryResults}-object back. If one of the passed parameters + * null is or if the queryString is empty, will null + * Delivered back. * * @param queryString - * die Suchanfrage + * the search query * @param searchStrategy - * die zu verwendende Suchstrategie + * the search strategy to use * @param datasources * Data source to use. * @throws IllegalArgumentException - * falls eine Datenquelle, in der gesucht werden soll, nicht existiert + * if a data source in which to search does not exist * @return Results as an Iterable of Dataset as {@link QueryResults} */ public static QueryResults search(String queryString, SearchStrategy searchStrategy, @@ -86,9 +86,9 @@ public static QueryResults search(String queryString, SearchStrategy searchStrat } /** - * Führt die Ergenismengen zusammen. Dabei werden mehrfache Ergebnisse ausgefiltert. + * Merges the sets of results. Multiple results are filtered out. * - * @return bereinigte Ergebnisliste. + * @return cleaned result list. */ private static QueryResults mergeListOfQueryResultsList(List listOfQueryResultsList) { @@ -115,35 +115,35 @@ private static QueryResults mergeListOfQueryResultsList(List listO } /** - * Liefert zur Anfrage queryString eine Liste von {@link Query}s, die der Reihe nach probiert - * werden sollten, gemäß der Suchstrategie searchStrategy (siehe - * {@link SearchStrategy#parse(ConfigThingy)}). Gibt es für die übergebene Anzahl Wörter keine - * Suchstrategie, so wird solange das letzte Wort entfernt bis entweder nichts mehr übrig ist oder - * eine Suchstrategie für die Anzahl Wörter gefunden wurde. + * Returns a list of {@link Query}s for the queryString, which are tried in order + * should be, according to the search strategy searchStrategy (Please refer + * {@link SearchStrategy#parse(ConfigThingy)}). There are none for the number of words passed + * Search strategy, the last word is removed until there is either nothing left or + * a search strategy for the number of words was found. * - * @return die leere Liste falls keine Liste bestimmt werden konnte. + * @return the empty list if no list could be determined. */ private static List parseQuery(SearchStrategy searchStrategy, String queryString) { List queryList = new ArrayList<>(); - // Kommata durch Space ersetzen (d.h. "Benkmann,Matthias" -> "Benkmann + // Replace commas with space (i.e. "Benkmann,Matthias" -> "Benkmann // Matthias") queryString = queryString.replaceAll(",", " "); - // Suchstring zerlegen. + // Decompose search string. Stream queryStream = Arrays.stream(queryString.trim().split("\\p{Space}+")); - // Formatieren und leere Wörter entfernen + // Format and remove empty words String[] queryArray = queryStream.map(Search::formatQuery).filter(query -> query.length() != 0) .toArray(String[]::new); int count = queryArray.length; - // Passende Suchstrategie finden; falls nötig dazu Wörter am Ende weglassen. + // Find a suitable search strategy; If necessary, leave out words at the end. while (count >= 0 && searchStrategy.getTemplate(count) == null) --count; - // keine Suchstrategie gefunden + // no search strategy found if (count < 0) { return queryList; @@ -159,9 +159,9 @@ private static List parseQuery(SearchStrategy searchStrategy, String quer } /** - * Benutzerseitig wir nur ein einzelnes Sternchen am Ende eines Wortes akzeptiert. Deswegen - * entferne alle anderen Sternchen. Ein Punkt am Ende eines Wortes wird als Abkürzung - * interpretiert und durch Sternchen ersetzt. + * On the user side, only a single asterisk at the end of a word is accepted. Because of this + * remove all other asterisks. A period at the end of a word is called an abbreviation + * interpreted and replaced with asterisks. */ private static String formatQuery(String query) { @@ -180,9 +180,9 @@ private static String formatQuery(String query) } /** - * Nimmt ein Template für eine Suchanfrage entgegen (das Variablen der Form "${suchanfrageX}" - * enthalten kann) und instanziiert es mit Wörtern aus words, wobei nur die ersten wordcount - * Einträge von words beachtet werden. + * Accepts a template for a search query (the variable of the form "${searchX}" + * can contain) and instantiates it with words from words, where only the first wordcount + * Entries of words are respected. */ private static Query resolveTemplate(Query template, String[] words, int wordcount) { diff --git a/core/src/main/java/org/libreoffice/lots/db/SearchStrategy.java b/core/src/main/java/org/libreoffice/lots/db/SearchStrategy.java index e33548f0a..8c2c6a277 100644 --- a/core/src/main/java/org/libreoffice/lots/db/SearchStrategy.java +++ b/core/src/main/java/org/libreoffice/lots/db/SearchStrategy.java @@ -32,22 +32,22 @@ import org.libreoffice.lots.config.ConfigThingy; /** - * Eine Suchstrategie liefert für eine gegebene Wortzahl eine Liste von Templates für - * Suchanfragen, die der Reihe nach mit den Wörtern probiert werden sollen bis ein - * Ergebnis gefunden ist. + * A search strategy returns a list of templates for a given word count + * Search queries to be tried in order with the words to a + * Result is found. */ public class SearchStrategy { /** - * Bildet eine Wortanzahl ab auf eine Liste von {@link Query}-Objekten, die - * passende Templates darstellen. + * Maps a word count to a list of {@link Query} objects that + * display suitable templates. */ private Map> mapWordcountToListOfQuerys; /** - * {@link #mapWordcountToListOfQuerys} wird per Referenz eingebunden und - * entsprechende Ergebnisse aus dieser Map werden von {@link #getTemplate(int)} - * zurückgeliefert. + * {@link #mapWordcountToListOfQuerys} is included by reference and + * corresponding results from this map are provided by {@link #getTemplate(int)} + * returned. */ private SearchStrategy() { @@ -55,12 +55,12 @@ private SearchStrategy() } /** - * Parst den "SearchStrategy"-Abschnitt von conf und liefert eine entsprechende + * Parses the "SearchStrategy" section of conf and returns an appropriate one * SearchStrategy. * * @param conf - * das {@link ConfigThingy}, dessen "SearchStrategy"-Abschnitt geparst - * werden soll. + * the {@link ConfigThingy} parsing its "SearchStrategy" section + * shall be. */ public static SearchStrategy parse(ConfigThingy conf) { @@ -106,13 +106,13 @@ private void addListOfQueryParts(int wordcount, String datasource, Listnull falls keine Strategie für den gegebenen wordcount - * vorhanden ist. + * @return null if no strategy for the given wordcount + * is available. */ public List getTemplate(int wordcount) { diff --git a/core/src/main/java/org/libreoffice/lots/db/SimpleDataset.java b/core/src/main/java/org/libreoffice/lots/db/SimpleDataset.java index bf80ab5e7..f480aa552 100644 --- a/core/src/main/java/org/libreoffice/lots/db/SimpleDataset.java +++ b/core/src/main/java/org/libreoffice/lots/db/SimpleDataset.java @@ -29,7 +29,7 @@ import org.libreoffice.lots.util.L; /** - * Eine simple Implementierung des Interfaces Dataset. + * A simple implementation of the Dataset interface. */ public class SimpleDataset implements Dataset { @@ -38,15 +38,15 @@ public class SimpleDataset implements Dataset private String key; /** - * Erzeugt ein SimpleDataset, das eine Kopie von ds ist. Das erzeugte SimpleDataset - * ist von schema und ds unabhängig und hält keine Verknüpfungen darauf. + * Creates a SimpleDataset that is a copy of ds. The generated SimpleDataset + * is independent of schema and ds and keeps no links to them. * * @param schema - * enthält die Namen aller zu kopierenden Spalten + * contains the names of all columns to be copied * @param ds * der zu kopierende Datensatz. * @throws ColumnNotFoundException - * falls eine Spalte aus schema dem Datensatz ds nicht bekannt ist + * if a column from schema is not known to the data set ds */ public SimpleDataset(Collection schema, Dataset ds) throws ColumnNotFoundException @@ -60,10 +60,9 @@ public SimpleDataset(Collection schema, Dataset ds) } /** - * Erzeugt ein SimpleDataset, das den Schlüssel key hat und dessen Daten von der - * Map data geliefert werden. Das Schema wird implizit durch die Schlüssel - * bestimmt, die data kennt (d.h. wenn data.containsKey(column), dann ist column im - * Schema). ACHTUNG! Sowohl schema als auch data werden per Referenz eingebunden. + * Create a SimpleDataset that has the key 'key' and its data is provided by the data map. + * The schema is implicitly determined by the keys that data knows (i.e., if data.containsKey(column), + * then column is in the schema). WARNING! Both the schema and data are included by reference. */ public SimpleDataset(String key, Map data) { diff --git a/core/src/main/java/org/libreoffice/lots/db/ThingyDatasource.java b/core/src/main/java/org/libreoffice/lots/db/ThingyDatasource.java index 4fb8794bb..267a083ba 100644 --- a/core/src/main/java/org/libreoffice/lots/db/ThingyDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/ThingyDatasource.java @@ -48,16 +48,16 @@ public class ThingyDatasource extends RAMDatasource private static final Pattern SPALTENNAME = Pattern.compile("^[a-zA-Z_][a-zA-Z_0-9]*$"); /** - * Erzeugt eine neue ThingyDatasource. + * Creates a new ThingyDatasource. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser - * ThingyDatasource bereits vollständig instanziierten Datenquellen. + * contains all up to the time of the definition of this + * ThingyDatasource already fully instantiated data sources. * @param sourceDesc - * der "DataSource"-Knoten, der die Beschreibung dieser - * ThingyDatasource enthält. + * the "DataSource" node, which contains the description of this + * Includes ThingyDatasource. * @param context - * der Kontext relativ zu dem URLs aufgelöst werden sollen. + * the context relative to which URLs should be resolved. */ public ThingyDatasource(Map nameToDatasource, ConfigThingy sourceDesc, URL context) throws IOException @@ -152,7 +152,7 @@ private String[] parseKeys(ConfigThingy sourceDesc, String name, List sc try { ConfigThingy keys = sourceDesc.get("Schluessel"); - // Exception werfen, falls kein Schluessel angegeben + // Throw exception if no key is specified keys.getFirstChild(); for (ConfigThingy key : keys) { @@ -174,20 +174,20 @@ private String[] parseKeys(ConfigThingy sourceDesc, String name, List sc } /** - * Erzeugt ein neues MyDataset aus der Beschreibung dsDesc. Die Methode - * erkennt automatisch, ob die Beschreibung in der Form ("Spaltenwert1", - * "Spaltenwert2",...) oder der Form (Spalte1 "Wert1" Spalte2 "Wert2" ...) - * ist. + * Creates a new MyDataset from the dsDesc description. The method + * automatically detects whether the description is in the form ("ColumnValue1", + * "ColumnValue2",...) or the form (Column1 "Value1" Column2 "Value2" ...) + * is. * * @param schema - * das Datenbankschema + * the database schema * @param schemaOrdered - * das Datenbankschema mit erhaltener Spaltenreihenfolge entsprechend - * Schema-Sektion. + * the database schema with preserved column order accordingly + * Schema section. * @param keyCols * die Schlüsselspalten * @throws ConfigurationErrorException - * im Falle von Verstössen gegen diverse Regeln. + * in the event of violations of various rules. */ private Dataset createDataset(ConfigThingy dsDesc, List schema, String[] schemaOrdered, String[] keyCols) @@ -212,11 +212,11 @@ private Dataset createDataset(ConfigThingy dsDesc, List schema, String[] } /** - * Erzeugt ein neues MyDataset aus der Beschreibung dsDesc. dsDesc muss in der - * Form (Spalte1 "Spaltenwert1" Spalte2 "Spaltenwert2 ...) sein. + * Creates a new MyDataset from the dsDesc description. dsDesc must be in the + *Form (Column1 "ColumnValue1" Column2 "ColumnValue2 ...).. * * @throws ConfigurationErrorException - * bei verstössen gegen diverse Regeln + * in case of violations of various rules */ private Dataset createDatasetUnordered(ConfigThingy dsDesc, List schema, String[] keyCols) { // TESTED @@ -238,11 +238,11 @@ private Dataset createDatasetUnordered(ConfigThingy dsDesc, List schema, } /** - * Erzeugt ein neues MyDataset aus der Beschreibung dsDesc. dsDesc muss in der - * Form ("Spaltenwert1" "Spaltenwert2 ...) sein. + * Creates a new MyDataset from the dsDesc description. dsDesc must be in the + * Form("columnvalue1" "columnvalue2 ...) to be. * * @throws ConfigurationErrorException - * bei verstössen gegen diverse Regeln + * in case of violations of various rules */ private Dataset createDatasetOrdered(ConfigThingy dsDesc, List schema, String[] schemaOrdered, String[] keyCols) @@ -288,11 +288,11 @@ public MyDataset(List schema, Map data, String[] keyCols } /** - * Setzt aus den Werten der Schlüsselspalten separiert durch KEY_SEPARATOR - * den Schlüssel zusammen. + * Sets from the values ​​of the key columns separated by KEY_SEPARATOR + * the key together. * * @param keyCols - * die Namen der Schlüsselspalten + * the names of the key columns */ private void initKey(String[] keyCols) { // TESTED diff --git a/core/src/main/java/org/libreoffice/lots/db/UnionDatasource.java b/core/src/main/java/org/libreoffice/lots/db/UnionDatasource.java index db49b7c25..8d0673abc 100644 --- a/core/src/main/java/org/libreoffice/lots/db/UnionDatasource.java +++ b/core/src/main/java/org/libreoffice/lots/db/UnionDatasource.java @@ -38,7 +38,7 @@ import org.libreoffice.lots.util.L; /** - * Datasource, die die Vereinigung 2er Datasources darstellt + * Datasource that represents the union of 2 datasources */ public class UnionDatasource extends Datasource { @@ -55,17 +55,17 @@ public class UnionDatasource extends Datasource private String name; /** - * Erzeugt eine neue UnionDatasource. + * Creates a new UnionDatasource. * * @param nameToDatasource - * enthält alle bis zum Zeitpunkt der Definition dieser UnionDatasource - * bereits vollständig instanziierten Datenquellen. + * contains all up to the time this UnionDatasource was defined + * Already fully instantiated data sources. * @param sourceDesc - * der "DataSource"-Knoten, der die Beschreibung dieser UnionDatasource - * enthält. + * the "DataSource" node, which contains the description of this UnionDatasource + * contains. * @param context - * der Kontext relativ zu dem URLs aufgelöst werden sollen (zur Zeit nicht - * verwendet). + * the context relative to which URLs should be resolved (currently not + * used). */ public UnionDatasource(Map nameToDatasource, ConfigThingy sourceDesc, URL context) @@ -88,12 +88,12 @@ public UnionDatasource(Map nameToDatasource, + "Referenced datasource \"{1}\" missing or defined incorrectly", name, source2Name)); /* - * Anmerkung: Die folgende Bedingung ist "unnötig" streng, aber um sie - * aufzuweichen (z.B. Gesamtschema ist Vereinigung der Schemata) wäre es - * erforderlich, einen Dataset-Wrapper zu implementieren, der dafür sorgt, dass - * alle Datasets, die in QueryResults zurück- geliefert werden das selbe Schema - * haben. Solange dafür keine Notwendigkeit ersichtlich ist, spare ich mir diesen - * Aufwand. + * Note: The following condition is "unnecessarily" strict, but around them + * softening it (e.g. overall schema is a union of schemas) would be it + * required to implement a dataset wrapper that ensures that + * all datasets returned in QueryResults -the same schema + * have. As long as there is no obvious need for it, I'll save it + * Expense. */ List schema1 = source1.getSchema(); List schema2 = source2.getSchema(); diff --git a/core/src/main/java/org/libreoffice/lots/dialog/Dialog.java b/core/src/main/java/org/libreoffice/lots/dialog/Dialog.java index 76b0ea980..8dbcdc0ea 100644 --- a/core/src/main/java/org/libreoffice/lots/dialog/Dialog.java +++ b/core/src/main/java/org/libreoffice/lots/dialog/Dialog.java @@ -30,74 +30,74 @@ import org.libreoffice.lots.func.FunctionLibrary; /** - * Ein Dialog, der dem Benutzer erlaubt verschiedenen Werte zu setzen. + * A dialog that allows the user to set different values. */ public interface Dialog { /** - * Liefert die Instanz dieses Dialogs für den gegebenen context (neu erstellt, - * falls bisher noch nicht verwendet). + * Returns the instance of this dialog for the given context (newly created, + * if not used yet). * * @param context - * Für jeden Kontext hält der Dialog eine unabhängige Kopie von seinem - * Zustand vor. Auf diese Weise lässt sich der Dialog an verschiedenen - * Stellen unabhängig voneinander einsetzen. ACHTUNG! Diese Map wird nicht - * als Schlüssel verwendet, sondern in ihr werden Werte abgelegt. + * For each context, the dialog keeps an independent copy of its + * state before. In this way, the dialogue can take place in different ways + * Use positions independently of each other. DANGER! This map will not + * used as a key, but values ​​are stored in it. * @throws ConfigurationErrorException - * wenn der Dialog mit fehlerhaften Daten initialisiert wurde (und der - * Fehler erst bei der Instanziierung diagnostiziert werden konnte). + * if the dialog was initialized with erroneous data (and the + * error could only be diagnosed during instantiation). */ public Dialog instanceFor(Map context); /** - * Liefert den durch id identifizierten Wert des Dialogs. Falls der Dialog noch - * nicht aufgerufen wurde wird ein Standardwert geliefert (typischerweise der leere - * String). Der Rückgabewert null ist ebenfalls möglich und signalisiert, dass der - * Dialog das entsprechende Feld nicht hat und auch nie haben wird. Die Rückgabe - * von null ist in diesem Fall allerdings nicht verpflichtend, sondern es ist - * ebenfalls der leere String möglich. Die Rückgabe von null sollte jedoch - * erfolgen, falls es dem Dialog irgendwie möglich ist. + * Returns the value of the dialog identified by id. If the dialogue still + * was not called, a default value is returned (typically the empty + * string). The return value null is also possible and indicates that the + * Dialog does not and never will have the corresponding field. The return + * of zero is not mandatory in this case, it is + * the empty string is also possible. However, returning null should + * take place if it is somehow possible for the dialogue. * - * Diese Funktion darf nur für mit instanceFor() erzeugte Instanzen aufgerufen - * werden. Ansonsten liefert sie immer null. Diese Funktion ist Thread-safe. - * Insbesondere muss sie nicht im EDT aufgerufen werden. Sie kann sowohl vor, - * während als auch nach dem Aufruf von show() aufgerufen werden, auch nachdem der - * Dialog schon geschlossen wurde. + * This function may only be called for instances created with instanceFor() + * become. Otherwise it always returns zero. This function is thread safe. + * In particular, it does not have to be called in EDT. She can + * be called both during and after the call to show(), even after the + * Dialog has already been closed. */ public Object getData(String id); /** - * Liefert eine Menge von ids, für die {@link #getData(String)} niemals null - * liefert. Dies ist nicht zwangsweise eine vollständige Liste aller ids, für die - * der Dialog Werte zurückliefern kann. Es ist ebenfalls nicht garantiert, dass der - * Dialog jemeils für eine dieser ids etwas anderes als den leeren String - * zurückliefert. Diese Funktion kann schon vor instanceFor() aufgerufen werden, es - * ist jedoch möglich, dass bei Aufruf für eine mit instanceFor() erzeugte Instanz - * mehr Information (d.h. eine größere Menge) zurückgeliefert wird. Das - * zurückgelieferte Objekt darf verändert werden. Dies hat keine Auswirkungen auf - * den Dialog. + * Returns a set of ids for which {@link #getData(String)} is never null + * delivers. This is not necessarily a complete list of all ids for which + * the dialog can return values. It is also not guaranteed that the + * Dialogue always displays something other than the empty string for one of these ids + * returns. This function can be called before instanceFor(), it + * However, it is possible that when called for an instance created with instanceFor() + * more information (i.e. a larger amount) is returned. The + * Returned object may be changed. This has no effect + * the dialogue. */ public Collection getSchema(); /** - * Zeigt den Dialog an. Diese Funktion darf nur für mit instanceFor() erzeugte - * Instanzen aufgerufen werden. Ansonsten tut sie nichts. + * Displays the dialog. This function may only be used for files created with instanceFor() + * Instances are called. Otherwise she does nothing. * * @param dialogEndListener - * falls nicht null, wird die + * if not null, the * {@link ActionListener#actionPerformed(java.awt.event.ActionEvent)} - * Methode aufgerufen (im Event Dispatching Thread), nachdem der Dialog - * geschlossen wurde. Das actionCommand des ActionEvents gibt die Aktion - * an, die das Beenden des Dialogs veranlasst hat. + * Method called (on the event dispatching thread) after the dialog + * has been closed. The actionCommand of the ActionEvent returns the action + * that caused the dialog to end. * @param funcLib - * falls der Dialog Funktionen auswertet, so werden Referenzen auf - * Funktionen mit dieser Bibliothek aufgelöst. + * If the dialog evaluates functions, references are made to + * Functions resolved with this library. * @param dialogLib - * falls der Dialog wiederum Funktionsdialoge unterstützt, so werden - * Referenzen auf Funktionsdialoge über diese Bibliothek aufgelöst. + * if the dialog in turn supports function dialogs, then + * Resolved references to function dialogs about this library. * @throws ConfigurationErrorException - * wenn der Dialog mit fehlerhaften Daten initialisiert wurde (und der - * Fehler erst bei der Anzeige diagnostiziert werden konnte). + * if the dialog was initialized with erroneous data (and the + * error could only be diagnosed when the display was displayed). */ public void show(ActionListener dialogEndListener, FunctionLibrary funcLib, DialogLibrary dialogLib); } diff --git a/core/src/main/java/org/libreoffice/lots/dialog/DialogFactory.java b/core/src/main/java/org/libreoffice/lots/dialog/DialogFactory.java index 093408a79..3eb000f99 100644 --- a/core/src/main/java/org/libreoffice/lots/dialog/DialogFactory.java +++ b/core/src/main/java/org/libreoffice/lots/dialog/DialogFactory.java @@ -46,16 +46,15 @@ private DialogFactory() } /** - * Parst die "FunctionDialogs" Abschnitte aus conf und liefert als Ergebnis eine - * DialogLibrary zurück. + * Paste the "Function Dialogs" sections from conf and return a DialogLibrary as a result. * * @param baselib - * falls nicht-null wird diese als Fallback verlinkt, um Dialoge zu - * liefern, die anderweitig nicht gefunden werden. + * if non-null this is linked as a fallback to open dialogs + * provide information that cannot be found elsewhere. * @param context - * der Kontext in dem in Dialogen enthaltene Funktionsdefinitionen - * ausgewertet werden sollen (insbesondere DIALOG-Funktionen). ACHTUNG! - * Hier werden Werte gespeichert, es ist nicht nur ein Schlüssel. + * the context in which function definitions contained in dialogs + * should be evaluated (especially DIALOG functions). DANGER! + * This is where values ​​are stored, it's not just a key. */ public static DialogLibrary parseFunctionDialogs(ConfigThingy conf, DialogLibrary baselib, Map context) diff --git a/core/src/main/java/org/libreoffice/lots/dialog/DialogLibrary.java b/core/src/main/java/org/libreoffice/lots/dialog/DialogLibrary.java index 120fd38eb..0a92a072f 100644 --- a/core/src/main/java/org/libreoffice/lots/dialog/DialogLibrary.java +++ b/core/src/main/java/org/libreoffice/lots/dialog/DialogLibrary.java @@ -28,7 +28,7 @@ import org.libreoffice.lots.util.L; /** - * Eine Bibliothek von benannten Dialogs. + * A library of named dialogs. * @author Matthias Benkmann (D-III-ITD 5.1) */ public class DialogLibrary @@ -38,7 +38,7 @@ public class DialogLibrary /** - * Erzeugt eine leere Dialogsbibliothek. + * Creates an empty dialog library. */ public DialogLibrary() { @@ -46,9 +46,9 @@ public DialogLibrary() } /** - * Erzeugt eine Dialogsbibliothek, die baselib referenziert (nicht kopiert!). - * baselib wird immer dann befragt, wenn die Dialogsbibliothek selbst keinen - * Dialog des entsprechenden Namens enthält. + * Creates a dialog library that references (not copies!) baselib. + * baselib is always consulted if the dialog library itself does not have one + * Dialog contains the corresponding name. * @param baselib */ public DialogLibrary(DialogLibrary baselib) @@ -57,7 +57,7 @@ public DialogLibrary(DialogLibrary baselib) } /** - * Fügt dialog dieser Dialogsbibliothek unter dem Namen dlgName hinzu. + * Adds dialog to this dialog library under the name dlg name. */ public void add(String dlgName, Dialog dialog) { @@ -69,11 +69,11 @@ public void add(String dlgName, Dialog dialog) } /** - * Liefert den Dialog namens dlgName zurück oder null, falls kein Dialog - * mit diesem Namen bekannt ist. Wurde die Dialogsbibliothek mit einer - * Referenz auf eine andere Bibliothek initialisiert, so wird diese - * befragt, falls die Dialogsbibliothek selbst keinen Dialog des entsprechenden - * Namens kennt. + * Returns the dialog named dlgName or null if no dialog + * known by that name. Was the dialog library with a + * Initialized reference to another library, this one will be used + * queried if the dialog library itself does not have a dialog of the corresponding + * Knows name. */ public Dialog get(String dlgName) { diff --git a/core/src/main/java/org/libreoffice/lots/document/AnnotationBasedPersistentDataContainer.java b/core/src/main/java/org/libreoffice/lots/document/AnnotationBasedPersistentDataContainer.java index f3ef1e01a..def05bf81 100644 --- a/core/src/main/java/org/libreoffice/lots/document/AnnotationBasedPersistentDataContainer.java +++ b/core/src/main/java/org/libreoffice/lots/document/AnnotationBasedPersistentDataContainer.java @@ -53,7 +53,7 @@ import org.libreoffice.lots.util.Utils; /** - * Implementiert die alte Zugriffsmethode auf persistente Daten in Notizen. + * Implements the old method of accessing persistent data in notes. * * @author Christoph Lutz (D-III-ITD-D101) */ @@ -65,30 +65,30 @@ public class AnnotationBasedPersistentDataContainer implements .getLogger(AnnotationBasedPersistentDataContainer.class); /** - * Der Name des Frames in dem der WollMux seine Metadaten speichert. + * The name of the frame in which WollMux stores its metadata. */ private static final String WOLLMUX_FRAME_NAME = "WollMuxDaten"; /** - * Maximale Länge von Textfeldern, die der WollMux schreibt. Die Länge 16000 - * wurde gewählt, wegen http://qa.openoffice.org/issues/show_bug.cgi?id=108709. + * Maximum length of text fields that WollMux writes. The length 16000 + * was chosen because of http://qa.openoffice.org/issues/show_bug.cgi?id=108709. */ private static final int TEXTFIELD_MAXLEN = 16000; /** - * Das Dokument, in dem die Daten gespeichert werden. + * The document in which the data is stored. */ private XTextDocument doc; /** - * Enthält die dataIDs, die vor dem letzten Aufruf von flush verändert wurden und - * wird für den Workaround für OOo-Issue 100374 benötigt. Kann mit Entfernen des - * Workarounds auch wieder entfernt werden. + * Contains the dataIDs that were changed before the last call to flush and + * is required for the workaround for OOo issue 100374. Can be done with removing the + * Workarounds can also be removed again. */ private HashSet modifiedDataIDs; /** - * Erzeugt einen neuen persistenten Datenspeicher im Dokument doc. + * Creates a new persistent data store in the document doc. */ public AnnotationBasedPersistentDataContainer(XTextDocument doc) { @@ -97,8 +97,8 @@ public AnnotationBasedPersistentDataContainer(XTextDocument doc) } /** - * Die Methode liefert die unter ID dataId gespeicherten Daten zurück oder null, - * wenn keine vorhanden sind. + * The method returns the data stored under ID dataId or null, + * if none exist. */ @Override public String getData(DataID dataId) @@ -118,17 +118,17 @@ public String getData(DataID dataId) } /** - * Liefert alle Informations-Textfelder mit Id fieldName zurück. + * Returns all information text fields with Id fieldName. * * @param create - * falls true so werden entsprechende Felder angelegt, wenn sie nicht - * existieren. - * @size falls create == true werden soviele Felder angelegt, dass darin size - * Zeichen aufgeteilt in TEXTFIELD_MAXLEN lange Blöcke untergebracht werden - * können. Eventuell vorhandene überschüssige Felder werden gelöscht. Auch - * bei size == 0 wird mindestens ein Block geliefert. - * @return leeren Vector falls das Feld nicht existiert und create == false oder - * falls ein Fehler auftritt. + * if true then corresponding fields will be created, if not + * exist. + * @size falls create == true so many fields are created that size + * Characters split into TEXTFIELD_MAXLEN long blocks to be accommodated + * can. Any excess fields will be deleted. Also + * if size == 0, at least one block is returned. + * @return empty Vector if field does not exist and create == false or + * if an error occurs. */ private List getWollMuxTextFields(String fieldName, boolean create, int size) @@ -202,8 +202,7 @@ private List getWollMuxTextFields(String fieldName, boolean create, } /* - * Falls create == true und zuviele Felder gefunden wurden, dann loesche - * die überzähligen. + * If create == true and too many fields were found, then delete the extra ones. */ if (create && textfields.size() > blockCount) { @@ -216,8 +215,8 @@ private List getWollMuxTextFields(String fieldName, boolean create, } /* - * Falls create == true und zu wenige Felder gefunden wurden, dann erzeuge - * zusätzliche. + * If create == true and too few fields were found, then create + * additional. */ if (create && textfields.size() < blockCount) { @@ -243,8 +242,8 @@ private List getWollMuxTextFields(String fieldName, boolean create, } /** - * Speichert dataValue mit der id dataId persistent im Dokument. Falls bereits - * Daten mit der selben dataId vorhanden sind, werden sie überschrieben. + * Stores dataValue with the id dataId persistently in the document. If already + * If there is data with the same dataId, it will be overwritten. */ @Override public void setData(DataID dataId, String dataValue) @@ -283,7 +282,7 @@ public void setData(DataID dataId, String dataValue) } /** - * Entfernt die mit dataId bezeichneten Daten, falls vorhanden. + * Removes the data identified by dataId, if any. */ @Override public void removeData(DataID dataId) diff --git a/core/src/main/java/org/libreoffice/lots/document/ByteBufferInputStream.java b/core/src/main/java/org/libreoffice/lots/document/ByteBufferInputStream.java index 9858b9150..0dcb5e23e 100644 --- a/core/src/main/java/org/libreoffice/lots/document/ByteBufferInputStream.java +++ b/core/src/main/java/org/libreoffice/lots/document/ByteBufferInputStream.java @@ -29,7 +29,7 @@ import com.sun.star.io.XSeekable; /** - * Wrapper für ByteBuffer zur Benutzung mit UNO. + * Wrapper for ByteBuffer for use with UNO. */ public class ByteBufferInputStream implements XInputStream, XSeekable { diff --git a/core/src/main/java/org/libreoffice/lots/document/DocumentLoader.java b/core/src/main/java/org/libreoffice/lots/document/DocumentLoader.java index ff85e6136..2ea35fcef 100644 --- a/core/src/main/java/org/libreoffice/lots/document/DocumentLoader.java +++ b/core/src/main/java/org/libreoffice/lots/document/DocumentLoader.java @@ -48,8 +48,8 @@ import org.libreoffice.lots.util.L; /** - * Funktionen zum Laden und Einfügen von Dokumenten. Geladene Dokumente werden - * gecacht. + * Document loading and insertion features. Loaded documents will be + * cached. */ public class DocumentLoader { @@ -60,9 +60,9 @@ public class DocumentLoader private LoadingCache cache; /** - * Zugriff auf den DocumentLoader als Singleton. + * Access to the DocumentLoader as a singleton. * - * @return Singleton-Instanz des DocumentLoaders + * @return Singleton instance of DocumentLoader */ public static DocumentLoader getInstance() { @@ -105,11 +105,11 @@ private ByteBuffer downloadDocument(String url) } /** - * Lädt ein Dokument und fügt es an der Stelle von target ein. target muss den - * Service XDocumentInsertable unterstützen. + * Loads a document and inserts it in the location of target. Target must + * Support XDocumentInsertable service. * * @param target - * @param path URL des Dokuments + * @param path URL of the document */ public void insertDocument(Object target, String path) { @@ -129,16 +129,16 @@ public void insertDocument(Object target, String path) } /** - * Lädt ein Dokument und öffnet es. + * Loads a document and opens it. * * @param path - * URL des Dokuments + * URL of the document * @param asTemplate - * behandelt das Dokument als Template + * treats the document as a template * @param allowMacros - * erlaubt die Ausführung von Makros + * allows macros to be executed * - * @return Das geladene Dokument. + * @return The loaded document. */ public XComponent loadDocument(String path, boolean asTemplate, boolean allowMacros) diff --git a/core/src/main/java/org/libreoffice/lots/document/DocumentManager.java b/core/src/main/java/org/libreoffice/lots/document/DocumentManager.java index 81f5762ff..f5907abb5 100644 --- a/core/src/main/java/org/libreoffice/lots/document/DocumentManager.java +++ b/core/src/main/java/org/libreoffice/lots/document/DocumentManager.java @@ -50,7 +50,7 @@ import org.libreoffice.lots.former.FormularMax4kController; /** - * Verwaltet Informationen zu allen offenen OOo-Dokumenten. + * Manages information about all open OOo documents. * * @author Matthias Benkmann (D-III-ITD-D101) */ @@ -60,28 +60,28 @@ public class DocumentManager private static final Logger LOGGER = LoggerFactory.getLogger(DocumentManager.class); /** - * Attributname zur Einstellung des Speichermodus für persistente Daten + * Attribute name for setting the storage mode for persistent data */ private static final String PERSISTENT_DATA_MODE = "PERSISTENT_DATA_MODE"; /** - * Wert 'annotation' des Attributs PERSISTENT_DATA_MODE + * Wert 'annotation' does Attribute PERSISTENT DATA MODE */ private static final String PERSISTENT_DATA_MODE_ANNOTATION = "annotation"; /** - * Wert 'transition' des Attributs PERSISTENT_DATA_MODE + * Wert 'transition' of PERSISTENT_DATA_MODE Attributes */ private static final String PERSISTENT_DATA_MODE_TRANSITION = "transition"; /** - * Wert 'rdf' des Attributs PERSISTENT_DATA_MODE + * Wert 'rdf' of PERSISTENT_DATA_MODE Attributes */ private static final String PERSISTENT_DATA_MODE_RDF = "rdf"; /** - * Wert 'rdfReadLegacy' des Attributs PERSISTENT_DATA_MODE + * Wert 'rdfReadLegacy' des Attributes PERSISTENT DATA MODE */ private static final String PERSISTENT_DATA_MODE_RDFREADLEGACY = "rdfReadLegacy"; /** - * Verwaltet Informationen zu allen offenen OOo-Dokumenten. + * Manages information about all open OOo documents. */ private static DocumentManager docManager; @@ -90,8 +90,8 @@ public class DocumentManager private Map controller = new HashMap<>(); /** - * Enthält alle registrierten XEventListener, die bei Statusänderungen der - * Dokumentbearbeitung informiert werden. + * Contains all registered XEventListeners that are activated when the status changes + * Document processing to be informed. */ private List registeredDocumentEventListener; @@ -100,8 +100,8 @@ private DocumentManager() { } /** - * Fügt compo den gemanageten Objekten hinzu, wobei die für Textdokumente - * relevanten Informationen hinterlegt werden. + * Adds compo to managed objects, with those for text documents + * Relevant information is stored. */ public void addTextDocument(XTextDocument compo) { @@ -116,9 +116,9 @@ public Map getTextDocumentList() { } /** - * Fügt compo den gemanageten Objekten hinzu, ohne weitere Informationen zu - * hinterlegen. compo ist also ein Objekt, an dem für den WollMux nur interessant - * ist, dass es existiert. + * Adds compo to the managed objects without further information + * deposit. So compo is an object that is only interesting for WollMux + * is that it existst. */ public synchronized void add(XComponent compo) { @@ -126,12 +126,12 @@ public synchronized void add(XComponent compo) } /** - * Entfernt alle Informationen über compo (falls vorhanden) aus diesem Manager. + * Removes all information about compo (if any) from this manager. * - * compo wird hier zur Optimierung nur als Object erwartet (spart einen - * vorangehenden UNO-Cast auf XComponent). + * compo is only expected as an object here for optimization (saves a + * previous UNO cast on XComponent). * - * @return die entfernten Informationen oder null falls keine vorhanden. + * @return the information removed or null if none exists. */ public synchronized Info remove(Object compo) { @@ -139,8 +139,8 @@ public synchronized Info remove(Object compo) } /** - * Liefert die über dieses Objekt bekannten Informationen oder null, falls das - * Objekt dem Manager nicht bekannt ist. + * Returns the information known about this object, or null if that + * Object unknown to manager. */ public synchronized Info getInfo(XComponent compo) { @@ -148,8 +148,8 @@ public synchronized Info getInfo(XComponent compo) } /** - * Fügt infoCollector alle Dokumente hinzu für die das - * OnWollMuxProcessingFinished-Event bereits verschickt wurde. + * Adds all documents to infoCollector for the das + * OnWollMuxProcessingFinished event has already been sent. */ public synchronized void getProcessedDocuments(Collection infoCollector) { @@ -166,9 +166,9 @@ public synchronized void getProcessedDocuments(Collection infoCollec } /** - * Setzt in den Informationen zu compo (falls dem DocumentManager bekannt) das Flag - * das anzeigt, dass das OnWollMuxProcessingFinished-Event für diese Komponente - * bereits verschickt wurde. + * Sets the flag in the information about compo (if known to the DocumentManager). + * indicating that the OnWollMuxProcessingFinished event for this component + * has already been sent. * * @param compo */ @@ -181,10 +181,10 @@ public synchronized void setProcessingFinished(XComponent compo) } /** - * Liefert einen Iterator auf alle registrierten XEventListener-Objekte, die über Änderungen am - * Status der Dokumentverarbeitung informiert werden sollen. + * Returns an iterator to all registered XEventListener objects that are to + * be informed about changes to the document processing status. * - * @return Liste aller registrierten XEventListener-Objekte. + * @return List of all registered XEventListener objects. */ public synchronized List getDocumentEventListener() { @@ -192,15 +192,14 @@ public synchronized List getDocumentEventListener() } /** - * Diese Methode registriert einen XEventListener, der Nachrichten empfängt wenn - * sich der Status der Dokumentbearbeitung ändert (z.B. wenn ein Dokument - * vollständig bearbeitet/expandiert wurde). Die Methode ignoriert alle - * XEventListenener-Instanzen, die bereits registriert wurden. - * Mehrfachregistrierung der selben Instanz ist also nicht möglich. - * - * Achtung: Die Methode darf nicht direkt von einem UNO-Service aufgerufen werden, - * sondern jeder Aufruf muss über den EventHandler laufen. Deswegen exportiert - * WollMuxSingleton auch nicht das XEventBroadcaster-Interface. + * This method registers an XEventListener that receives messages + * when the document processing status changes (e.g., when a document has been fully edited/expanded). + * The method ignores all XEventListener instances that have already been registered. + * Therefore, it is not possible to register the same instance multiple times. + * + * Caution: This method should not be called directly from a UNO service; instead, + * every call must go through the EventHandler. + * That's why the WollMuxSingleton does not export the XEventBroadcaster interface. */ public synchronized void addDocumentEventListener(XEventListener listener) { @@ -222,12 +221,11 @@ public synchronized void addDocumentEventListener(XEventListener listener) } /** - * Diese Methode deregistriert einen XEventListener wenn er bereits registriert - * war. + * This method deregisters an XEventListener if it was already registered. * - * Achtung: Die Methode darf nicht direkt von einem UNO-Service aufgerufen werden, - * sondern jeder Aufruf muss über den EventHandler laufen. Deswegen exportiert - * WollMuxSingleton auch nicht das XEventBroadcaster-Interface. + * Caution: This method should not be called directly from a UNO service; + * instead, every call must go through the EventHandler. + * That's why the WollMuxSingleton does not export the XEventBroadcaster interface. */ public synchronized void removeDocumentEventListener(XEventListener listener) { @@ -243,10 +241,10 @@ public synchronized void removeDocumentEventListener(XEventListener listener) } /** - * Liefert die zu diesem Dokument zugehörige FormularGUI, falls dem TextDocumentModel die Existent - * einer FormGUI über setFormGUI(...) mitgeteilt wurde - andernfalls wird null zurück geliefert. + * Returns the associated FormGUI for this document, if the TextDocumentModel + * has been informed of the existence of a FormGUI through setFormGUI(...); otherwise, null is returned. * - * @return Die FormularGUI des Formulardokuments oder null + * @return The FormGUI of the form document, or null */ public synchronized FormController getFormController(XTextDocument doc) { @@ -254,9 +252,9 @@ public synchronized FormController getFormController(XTextDocument doc) } /** - * Gibt dem TextDocumentModel die Existent der FormularGUI formGUI bekannt und wird vom - * DocumentCommandInterpreter in der Methode processFormCommands() gestartet hat, falls das - * Dokument ein Formulardokument ist. + * Announces the existence of the FormGUI 'formGUI' to the TextDocumentModel + * and is invoked by the DocumentCommandInterpreter in the method processFormCommands() + * if the document is a form documentt. * * @param doc * @param formModel @@ -267,8 +265,7 @@ public synchronized void setFormController(XTextDocument doc, FormController for } /** - * Setzt die Instanz des aktuell geöffneten, zu diesem Dokument gehörenden - * FormularMax4000. + * Sets the instance of the currently open FormularMax4000 associated with this document. * * @param max */ @@ -278,10 +275,10 @@ public synchronized void setCurrentFormularMax4000(XTextDocument doc, FormularMa } /** - * Liefert die Instanz des aktuell geöffneten, zu diesem Dokument gehörenden FormularMax4000 - * zurück, oder null, falls kein FormularMax gestartet wurde. + * Returns the instance of the currently open FormularMax4000 associated with this document, + * or null if no FormularMax has been started. * - * @return Den FormularMax4000 oder null. + * @return The FormularMax4000 or null. */ public synchronized FormularMax4kController getCurrentFormularMax4000(XTextDocument doc) { @@ -303,14 +300,13 @@ public static boolean hasTextDocumentController(XTextDocument doc) } /** - * Liefert das aktuelle TextDocumentModel zum übergebenen XTextDocument doc; - * existiert zu doc noch kein TextDocumentModel, so wird hier eines erzeugt und das - * neu erzeugte zurück geliefert. + * Returns the current TextDocumentModel for the given XTextDocument 'doc'; + * if there is no existing TextDocumentModel for 'doc', + * one is created and the newly created one is returned. * * @param doc - * Das XTextDocument, zu dem das zugehörige TextDocumentModel - * zurückgeliefert werden soll. - * @return Das zu doc zugehörige TextDocumentModel. + * The XTextDocument for which the associated TextDocumentModel should be returned. + * @return The TextDocumentModel associated with 'doc'. */ public static TextDocumentController getTextDocumentController(XTextDocument doc) { @@ -320,7 +316,7 @@ public static TextDocumentController getTextDocumentController(XTextDocument doc LOGGER.error("Irgendwer will hier ein TextDocumentModel für ein Objekt was der DocumentManager nicht kennt. " + "Das sollte nicht passieren!", new Exception()); - // Wir versuchen trotzdem sinnvoll weiterzumachen. + // We are still trying to proceed sensibly. getDocumentManager().addTextDocument(doc); info = getDocumentManager().getInfo(doc); } @@ -350,7 +346,7 @@ public static TextDocumentController getTextDocumentController(XFrame frame) } /** - * Liefert eine Referenz auf den von diesem WollMux verwendeten + * Returns a reference to the one used by this WollMux. * {@link DocumentManager}. */ public static DocumentManager getDocumentManager() @@ -364,14 +360,12 @@ public static DocumentManager getDocumentManager() public static class Info { /** - * Gibt an ob für das Dokument bereits ein OnWollMuxProcessingFinished-Event an - * die Listener verschickt wurde. + * Indicates whether an OnWollMuxProcessingFinished event has already been sent to the listeners for the document. */ private boolean processingFinished = false; /** - * Liefert true gdw für das Dokument bereits ein - * OnWollMuxProcessingFinished-Event an die Listener verschickt wurde. + * Returns true if an OnWollMuxProcessingFinished event has already been sent to the listeners for the document. */ public boolean isProcessingFinished() { @@ -379,11 +373,10 @@ public boolean isProcessingFinished() } /** - * Liefert das zu diesem Dokument gehörige TextDocumentModel. Falls es noch nicht - * angelegt wurde, wird es angelegt. + * Returns the TextDocumentModel associated with this document. If it has not been created yet, it will be created. * * @throws UnsupportedOperationException - * falls das Dokument kein TextDocument ist. + * If the document is not a TextDocument. */ public TextDocumentController getTextDocumentController() { @@ -391,8 +384,7 @@ public TextDocumentController getTextDocumentController() } /** - * Liefert true gdw dieses Dokument ein TextDocumentModel zugeordnet haben kann - * UND ein solches auch bereits angelegt wurde. + * Returns true if this document can be associated with a TextDocumentModel and one has already been created. */ public boolean hasTextDocumentModel() { @@ -400,7 +392,7 @@ public boolean hasTextDocumentModel() } /** - * Setzt das Flag, das mit {@link #isProcessingFinished()} abgefragt wird auf + * Sets the flag queried with {@link #isProcessingFinished()} * true. */ private void setProcessingFinished() @@ -451,8 +443,8 @@ public String toString() } /** - * Ruft die Dispose-Methoden von allen aktiven, dem TextDocumentModel zugeordneten - * Dialogen auf und gibt den Speicher des TextDocumentModels frei. + * Invokes the Dispose methods of all active dialogs associated with the + * TextDocumentModel and releases the memory of the TextDocumentModel. */ public synchronized void dispose(XTextDocument doc) { @@ -466,16 +458,14 @@ public synchronized void dispose(XTextDocument doc) } /** - * Liefert abhängig von der Konfigurationseinstellung PERSISTENT_DATA_MODE - * (annotation|transition|rdfReadLegacy|rdf) den dazugehörigen PersistentDataContainer für das - * Dokument doc. + * Depending on the configuration setting PERSISTENT_DATA_MODE (annotation|transition|rdfReadLegacy|rdf), + * it returns the corresponding PersistentDataContainer for the document 'doc'. * - * Die folgende Aufstellung zeigt das Verhalten der verschiedenen Einstellungen bezüglich der - * möglichen Kombinationen von Metadaten in den Ausgangsdokumenten und der Aktualisierung der - * Metadaten in den Ergebnisdokumenten. Ein "*" symbolisiert dabei, welcher Metadatencontainer - * jeweils aktuell ist bzw. bei Dokumentänderungen aktualisiert wird. + * The following table illustrates the behavior of different settings regarding the possible + * combinations of metadata in the source documents and the update of metadata in the result documents. + * An "*" symbolizes which metadata container is currently up-to-date or updated when document changes occur. * - * Ausgangsdokument -> bearbeitet durch -> Ergebnisdokument + * source document -> Edited by -> Results document * * [N*] -> annotation-Mode (WollMux-Alt) -> [N*] * @@ -483,7 +473,7 @@ public synchronized void dispose(XTextDocument doc) * * [N*] -> rdfReadLegacy-Mode -> [R*] * - * [N*] -> rdf-Mode: NICHT UNTERSTÜTZT + * [N*] -> rdf-Mode: NOT SUPPORTED * * [N*R*] -> annotation-Mode (WollMux-Alt) -> [N*R] * @@ -499,17 +489,17 @@ public synchronized void dispose(XTextDocument doc) * * [N*R] -> rdfReadLegacy-Mode -> [R*] * - * [N*R] -> rdf-Mode: NICHT UNTERSTÜTZT + * [N*R] -> rdf-Mode: NOT SUPPORTED * - * [NR*] -> annotation-Mode (WollMux-Alt) : NICHT UNTERSTÜTZT + * [NR*] -> annotation-Mode (WollMux-Alt) : NOT SUPPORTED * - * [NR*] -> transition-Mode: NICHT UNTERSTÜTZT + * [NR*] -> transition-Mode: NOT SUPPORTED * - * [NR*] -> rdfReadLegacy-Mode: NICHT UNTERSTÜTZT + * [NR*] -> rdfReadLegacy-Mode: NOT SUPPORTED * * [NR*] -> rdf -> [NR*] * - * [R*] -> annotation-Mode (WollMux-Alt): NICHT UNTERSTÜTZT + * [R*] -> annotation-Mode (WollMux-Alt): NOT SUPPORTED * * [R*] -> transition-Mode -> [N*R*] * @@ -517,8 +507,8 @@ public synchronized void dispose(XTextDocument doc) * * [R*] -> rdf-Mode -> [R*] * - * Agenda: [N]=Dokument mit Notizen; [R]=Dokument mit RDF-Metadaten; [NR]=Dokument mit Notizen und - * RDF-Metadaten; *=N/R enthält aktuellen Stand; + * Agenda: [N] = Document with notes; [R] = Document with RDF metadata; + * [NR] = Document with notes and RDF metadata; * = N/R contains current status; */ public static PersistentDataContainer createPersistentDataContainer( XTextDocument doc)