diff --git a/src/main/java/org/nanoboot/spriteutils/core/SpriteSheetRow.java b/src/main/java/org/nanoboot/spriteutils/core/SpriteSheetRow.java index 5780030..4d174b9 100644 --- a/src/main/java/org/nanoboot/spriteutils/core/SpriteSheetRow.java +++ b/src/main/java/org/nanoboot/spriteutils/core/SpriteSheetRow.java @@ -21,17 +21,22 @@ package org.nanoboot.spriteutils.core; import java.util.Arrays; import java.util.List; +import java.util.Optional; import lombok.Data; import lombok.ToString; /** - * + * Represents a row in a sprite sheet. + * This class is responsible for parsing and serializing sprite sheet rows from/to CSV format. + * * @author robertvokac */ @Data @ToString public class SpriteSheetRow { - + private static final String DELIMITER = ";"; + private static final String ID_DELIMITER = "__"; + private static final int MINIMUM_COLUMNS = 10; String file; String group; int numberInGroup; @@ -44,51 +49,73 @@ public class SpriteSheetRow { String notes; String tags; int numberPerSheet; - + /** + * Constructor to create a SpriteSheetRow from a CSV line. + * + * @param csvLine the CSV line containing the sprite sheet row data + @throws IllegalArgumentException if the CSV line does not contain enough columns or contains invalid data + */ public SpriteSheetRow(String csvLine) { - String[] csvColumn = csvLine.split(";"); - if (csvColumn.length < 10) { - throw new IllegalArgumentException("CSV line does not contain enough (10) columns."); + String[] csvColumns = csvLine.split(DELIMITER); + if (csvColumns.length < MINIMUM_COLUMNS) { + throw new IllegalArgumentException("CSV line does not contain enough columns."); } - int i = 0; - file = csvColumn[i++]; - group = csvColumn[i++]; - numberInGroup = Integer.parseInt(csvColumn[i++]); - row = Integer.parseInt(csvColumn[i++]); - column = Integer.parseInt(csvColumn[i++]); - x = csvColumn[i++].isBlank() ? -1 : Integer.parseInt(csvColumn[i - 1]); - y = Integer.parseInt(csvColumn[i++]); - width = Integer.parseInt(csvColumn[i++]); - height = Integer.parseInt(csvColumn[i++]); - if (column > 1) { - height = -height; - } - notes = csvColumn.length >= 10 ? csvColumn[i++] : ""; - tags = csvColumn.length > 11 ? csvColumn[i++] : ""; - } + try { + int i = 0; + file = csvColumns[i++]; + group = csvColumns[i++]; + numberInGroup = Integer.parseInt(csvColumns[i++]); + row = Integer.parseInt(csvColumns[i++]); + column = Integer.parseInt(csvColumns[i++]); + x = parseOptionalInt(csvColumns[i++]).orElse(-1); + y = Integer.parseInt(csvColumns[i++]); + width = Integer.parseInt(csvColumns[i++]); + height = Integer.parseInt(csvColumns[i++]); + notes = i < csvColumns.length ? csvColumns[i++] : ""; + tags = i < csvColumns.length ? csvColumns[i++] : ""; + numberPerSheet = i < csvColumns.length ? Integer.parseInt(csvColumns[i]) : 0; + // Adjust height if the column is greater than 1 + if (column > 1) { + height = -height; + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("CSV line contains invalid number format.", e); + } + } + /** + * Creates an ID for the sprite sheet row. + * + * @return the generated ID + */ public String createId() { - return file + __ + group + __ + numberInGroup; + return String.join(ID_DELIMITER, file, group, String.valueOf(numberInGroup)); } - private static final String __ = "__"; - private static final String DELIMITER = ";"; - + /** + * Converts the sprite sheet row to a CSV line. + * + * @return the CSV line representation of the sprite sheet row + */ public String toCsvLine() { List fields = Arrays.asList( - file, - group, - String.valueOf(numberInGroup), - String.valueOf(row), - String.valueOf(column), - String.valueOf(x), - String.valueOf(y), - String.valueOf(width), - String.valueOf(height), - notes, - tags, - String.valueOf(numberPerSheet) + file, group, String.valueOf(numberInGroup), String.valueOf(row), + String.valueOf(column), String.valueOf(x), String.valueOf(y), + String.valueOf(width), String.valueOf(height), notes, tags, + String.valueOf(numberPerSheet) ); return String.join(DELIMITER, fields); } - + /** + * Parses an optional integer from a string. + * + * @param value the string to parse + * @return an Optional containing the parsed integer, or empty if the string is blank + */ + private Optional parseOptionalInt(String value) { + try { + return value.isBlank() ? Optional.empty() : Optional.of(Integer.parseInt(value)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid integer format: " + value, e); + } + } }