Skip to content

Add Suffix Formatter - #4

Open
ankit27755 wants to merge 12 commits into
mainfrom
add-suffix-formatter
Open

Add Suffix Formatter#4
ankit27755 wants to merge 12 commits into
mainfrom
add-suffix-formatter

Conversation

@ankit27755

@ankit27755 ankit27755 commented Apr 30, 2025

Copy link
Copy Markdown
Owner

DeputyDev generated PR summary:


Size L: This PR changes include 219 lines and should take approximately 1-3 hours to review


The pull request titled "Add Suffix Formatter" introduces several changes to the codebase that focus on enhancing the ID generation and parsing functionality by adding support for suffixes. Here are the key modifications made in the PR:

  1. Introduction of Suffix in ID Generation:

    • A new SuffixIdFormatter class is introduced to handle IDs with suffixes.
    • The Id class is updated to include a suffix field alongside the existing prefix.
  2. Enhancements in ID Formatter Interface:

    • The IdFormatter interface now includes a getType() method to identify the type of formatter being used.
    • The IdParserType enum is added to distinguish between different formatter types such as DEFAULT and SUFFIX.
  3. Modifications in ID Generation and Parsing Logic:

    • The DefaultIdGenerator class is updated to support suffixes during ID generation.
    • The IdGeneratorBase class includes new methods to generate IDs with suffixes and formatters.
    • The IdParsers class is updated to parse IDs with suffixes using a pattern that recognizes suffixes and selects the appropriate formatter based on the parsed type.
  4. Performance Test Updates:

    • Performance test files are updated with new mean_ops values, indicating performance measurements post-implementation of changes.
  5. Testing Enhancements:

    • New tests are added to verify the correct parsing and generation of IDs with suffixes, ensuring that the new functionality works as expected.

The PR effectively extends the ID generation system to accommodate suffixes, providing more flexibility in how IDs are structured and parsed. This can be particularly useful in scenarios where additional categorization or differentiation of IDs is required.

Here's a snippet showing how the SuffixIdFormatter is implemented:

+public class SuffixIdFormatter implements IdFormatter {
+    private static final Pattern PATTERN = Pattern.compile("([A-Za-z]*)([0-9]{15})([0-9]{4})([0-9]{3})([0-9]{2})([0-9]*)");
+    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyMMddHHmmssSSS");
+
+    @Override
+    public IdParserType getType() {
+        return IdParserType.SUFFIX;
+    }
+
+    @Override
+    public String format(final DateTime dateTime,
+                         final int nodeId,
+                         final int randomNonce) {
+        return String.format("%s%04d%03d%02d", DATE_TIME_FORMATTER.print(dateTime), nodeId, randomNonce, getType().getValue());
+    }
+
+    @Override
+    public Optional<Id> parse(final String idString) {
+        val matcher = PATTERN.matcher(idString);
+        if (!matcher.find()) {
+            return Optional.empty();
+        }
+        return Optional.of(Id.builder()
+                .id(idString)
+                .prefix(matcher.group(1))
+                .suffix(matcher.group(6))
+                .node(Integer.parseInt(matcher.group(3)))
+                .exponent(Integer.parseInt(matcher.group(4)))
+                .generatedDate(DATE_TIME_FORMATTER.parseDateTime(matcher.group(2)).toDate())
+                .build());
+    }
+}

This PR is a comprehensive update that expands the functionality of the ID system, ensuring that IDs can now include suffixes, which are parsed and formatted correctly.


DeputyDev generated PR summary until 64b9b0f

return IdFormatters.original().parse(idString);
}

val parser = parserRegistry.get(Integer.parseInt(matcher.group(3)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SECURITY: When parsing IDs in the IdParsers.java file, the code attempts to convert the parsed parserType (matcher.group(3)) directly to an integer using Integer.parseInt without proper validation. If the regex matches unexpected inputs, this could lead to a NumberFormatException. While the catch block will handle this exception, it might mask specific parsing issues and make debugging harder.

val parserType = matcher.group(3);
if (parserType == null) {
    return IdFormatters.original().parse(idString);
}

try {
    int parserTypeInt = Integer.parseInt(parserType);
    val parser = parserRegistry.get(parserTypeInt);
    if (parser == null) {
        log.warn("Could not parse idString {}, Invalid formatter type {}", idString, parserType);
        return Optional.empty();
    }
    return parser.parse(idString);
} catch (NumberFormatException e) {
    log.warn("Invalid parser type format in idString {}: {}", idString, e.getMessage());
    return Optional.empty();
}

}

@Override
public Optional<Id> parse(final String idString) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SECURITY: In SuffixIdFormatter.parse(), the method directly accesses matcher group results without validating whether all expected groups are present. This could lead to NullPointerExceptions or incorrect data being used if the pattern matches in an unexpected way. Additionally, parsing operations (Integer.parseInt and parseDateTime) are performed without exception handling.

public Optional<Id> parse(final String idString) {
    val matcher = PATTERN.matcher(idString);
    if (!matcher.find() || matcher.groupCount() < 6) {
        return Optional.empty();
    }
    
    try {
        String prefix = matcher.group(1);
        String dateTimeStr = matcher.group(2);
        int node = Integer.parseInt(matcher.group(3));
        int exponent = Integer.parseInt(matcher.group(4));
        String suffix = matcher.group(6);
        
        return Optional.of(Id.builder()
                .id(idString)
                .prefix(prefix)
                .suffix(suffix)
                .node(node)
                .exponent(exponent)
                .generatedDate(DATE_TIME_FORMATTER.parseDateTime(dateTimeStr).toDate())
                .build());
    } catch (Exception e) {
        return Optional.empty();
    }
}

}

@Override
public IdParserType getType() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CODE_MAINTAINABILTIY: The newly added getType method in IdFormatter interface forces all existing implementations to be updated but Base36IdFormatter throws UnsupportedOperationException instead of providing a proper implementation. This creates technical debt as it will need to be fixed properly in the future.

// The entire Base36IdFormatter class should be updated to properly implement IdParserType,
// either by properly supporting the parser type mechanism or by creating a dedicated parser implementation.

@Getter
public enum IdParserType {
DEFAULT (0),
SUFFIX (11);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CODE_MAINTAINABILTIY: The IdParserType enum is missing a value for BASE36, even though there is a Base36IdFormatter implementation. This inconsistency in the type system creates a gap in the design where some formatters cannot be properly identified in the parser registry.

public enum IdParserType {
    DEFAULT (0),
    SUFFIX (11),
    BASE36 (12);  // Add enum value for Base36 format

    private final int value;

    IdParserType(final int value) {
        this.value = value;
    }


@Override
public IdParserType getType() {
throw new UnsupportedOperationException();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ERROR: The getType() method in Base36IdFormatter throws UnsupportedOperationException, which violates the Liskov Substitution Principle and can lead to runtime errors as it should return a proper IdParserType.
@Override
public IdParserType getType() {
    return IdParserType.BASE36; // Add this enum value to IdParserType
}

@deputydev-agent

Copy link
Copy Markdown

DeputyDev has completed a review of your pull request for commit 64b9b0f.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant