Coverage Summary for Class: CourseToGerman (org.kitodo.production.model.bibliography.course)
Class |
Class, %
|
Method, %
|
Line, %
|
CourseToGerman |
0%
(0/1)
|
0%
(0/8)
|
0%
(0/116)
|
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/
package org.kitodo.production.model.bibliography.course;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;
import org.kitodo.production.helper.DateUtils;
/**
* The static class CourseToGerman provides a toString() method to convert a
* course of appearance into a verbal description in German language.
*/
public class CourseToGerman {
/**
* Days of week’s names in German.
*
* <p>
* Joda time’s days of week are 1-based, where 1 references Monday through 7
* references Sunday. Therefore the “null” in first place.
*/
private static final String[] DAYS_OF_WEEK_NAMES = new String[] {null, "Montag", "Dienstag", "Mittwoch",
"Donnerstag", "Freitag", "Samstag", "Sonntag" };
/**
* Month’s names in German.
*
* <p>
* Joda time’s months are 1-based, therefore the “null” in first place.
*/
private static final String[] MONTH_NAMES = new String[] {null, "Januar", "Februar", "März", "April", "Mai", "Juni",
"Juli", "August", "September", "Oktober", "November",
"Dezember" };
private CourseToGerman() {
}
/**
* Returns a verbal description of the course of
* appearance in German.
*
* @return Verbal description of the course in German
*/
public static List<String> asReadableText(Course course) {
List<String> readableText = new ArrayList<>();
if (course.isEmpty()) {
return readableText;
}
Iterator<Block> blocks = course.iterator();
boolean hasPreviousBlock = false;
do {
Block block = blocks.next();
readableText.add(titleToString(block, hasPreviousBlock));
for (Issue issue : block.getIssues()) {
String irregularities = irregularitiesToString(issue);
if (irregularities != null) {
readableText.add(irregularities);
}
}
hasPreviousBlock = true;
} while (blocks.hasNext());
return readableText;
}
/**
* Formulates the regular appearance of a block
* in German language.
*
* @param block
* Titel to formulate
* @param subsequentBlock
* false for the first block, true otherwise
*/
private static String titleToString(Block block, boolean subsequentBlock) {
StringBuilder result = new StringBuilder(500);
if (!subsequentBlock) {
result.append("Die Zeitung erschien vom ");
appendDate(result, block.getFirstAppearance());
} else {
result.append("Ab dem ");
appendDate(result, block.getFirstAppearance());
result.append(" erschien die Zeitung unter dem gleichen Titel");
}
result.append(" bis zum ");
appendDate(result, block.getLastAppearance());
result.append(" regelmäßig ");
result.append(iterateOverIssues(block, result));
return result.toString();
}
private static String iterateOverIssues(Block block, StringBuilder result) {
int currentIssuesSize = block.getIssues().size();
Iterator<Issue> issueIterator = block.getIssues().iterator();
for (int issueIndex = 0; issueIndex < currentIssuesSize; issueIndex++) {
Issue issue = issueIterator.next();
result.append("an allen ");
int daysOfWeekCount = 0;
for (int dayOfWeek = DayOfWeek.MONDAY.getValue(); dayOfWeek <= DayOfWeek.SUNDAY.getValue(); dayOfWeek++) {
if (issue.isDayOfWeek(dayOfWeek)) {
result.append(DAYS_OF_WEEK_NAMES[dayOfWeek]);
result.append("en");
daysOfWeekCount++;
if (daysOfWeekCount < issue.getDaysOfWeek().size() - 1) {
result.append(", ");
}
if (daysOfWeekCount == issue.getDaysOfWeek().size() - 1) {
result.append(" und ");
}
}
}
result.append(" als ");
result.append(issue.getHeading());
if (issueIndex < currentIssuesSize - 2) {
result.append(", ");
}
if (issueIndex == currentIssuesSize - 2) {
result.append(" sowie ");
}
if (issueIndex == currentIssuesSize - 1) {
result.append(".");
}
}
return result.toString();
}
/**
* Formulates the irregularities of a
* given issue in German language.
*
* @param issue
* issues whose irregularities shall be formulated
*/
private static String irregularitiesToString(Issue issue) {
int additionsSize = issue.getAdditions().size();
int exclusionsSize = issue.getExclusions().size();
StringBuilder buffer = new StringBuilder((int) (Math.ceil(10.907 * (additionsSize + exclusionsSize)) + 500));
if (additionsSize == 0 && exclusionsSize == 0) {
return null;
}
buffer.append("Die Ausgabe „");
buffer.append(issue.getHeading());
buffer.append("“ erschien ");
if (exclusionsSize > 0) {
appendManyDates(buffer, issue.getExclusions(), false);
if (additionsSize > 0) {
buffer.append(", dafür jedoch ");
}
}
if (additionsSize > 0) {
appendManyDates(buffer, issue.getAdditions(), true);
}
buffer.append(".");
return buffer.toString();
}
/**
* Converts a lot of date objects into readable
* text in German language.
*
* @param buffer
* StringBuilder to write to
* @param dates
* Set of dates to convert to text
* @param signum
* sign, i.e. true for additions, false for exclusions
* @throws NoSuchElementException
* if dates has no elements
* @throws NullPointerException
* if buffer or dates is null
*/
private static void appendManyDates(StringBuilder buffer, Set<LocalDate> dates, boolean signum) {
if (signum) {
buffer.append("zusätzlich ");
} else {
buffer.append("nicht ");
}
TreeSet<LocalDate> orderedDates = dates instanceof TreeSet ? (TreeSet<LocalDate>) dates : new TreeSet<>(dates);
//TODO: there is something wrong with this whole iterator - investigate it
Iterator<LocalDate> datesIterator = orderedDates.iterator();
LocalDate current = datesIterator.next();
LocalDate next = datesIterator.hasNext() ? datesIterator.next() : null;
LocalDate overNext = datesIterator.hasNext() ? datesIterator.next() : null;
int previousYear = Integer.MIN_VALUE;
boolean nextInSameMonth;
boolean nextBothInSameMonth = next != null && DateUtils.sameMonth(current, next);
int lastMonthOfYear = DateUtils.lastMonthForYear(orderedDates, current.getYear());
do {
nextInSameMonth = nextBothInSameMonth;
nextBothInSameMonth = DateUtils.sameMonth(next, overNext);
if (previousYear != current.getYear()) {
buffer.append("am ");
}
buffer.append(current.getDayOfMonth());
buffer.append('.');
if (!nextInSameMonth) {
buffer.append(' ');
buffer.append(MONTH_NAMES[current.getMonthValue()]);
}
lastMonthOfYear = handleLastMonthOfYear(buffer, signum, orderedDates, current, next,
nextInSameMonth, nextBothInSameMonth, lastMonthOfYear);
previousYear = current.getYear();
current = next;
next = overNext;
overNext = datesIterator.hasNext() ? datesIterator.next() : null;
} while (current != null);
}
private static int handleLastMonthOfYear(
StringBuilder buffer, boolean signum, TreeSet<LocalDate> orderedDates,
LocalDate current, LocalDate next, boolean nextInSameMonth, boolean nextBothInSameMonth, int lastMonthOfYear) {
if (!DateUtils.sameYear(current, next)) {
buffer.append(' ');
buffer.append(current.getYear());
if (next != null) {
if (!DateUtils.sameYear(next, orderedDates.last())) {
buffer.append(", ");
} else {
buffer.append(" und ebenfalls ");
if (!signum) {
buffer.append("nicht ");
}
}
lastMonthOfYear = DateUtils.lastMonthForYear(orderedDates, next.getYear());
}
} else if (next != null) {
if (nextInSameMonth && nextBothInSameMonth
|| !nextInSameMonth && next.getMonthValue() != lastMonthOfYear) {
buffer.append(", ");
} else {
buffer.append(" und ");
}
}
return lastMonthOfYear;
}
/**
* Writes a date to the buffer.
*
* @param buffer
* Buffer to write to
* @param date
* Date to write
*/
private static void appendDate(StringBuilder buffer, LocalDate date) {
buffer.append(date.getDayOfMonth());
buffer.append(". ");
buffer.append(MONTH_NAMES[date.getMonthValue()]);
buffer.append(' ');
buffer.append(date.getYear());
}
}