diff --git a/cosid-core/src/main/java/me/ahoo/cosid/converter/DatePrefixIdConverter.java b/cosid-core/src/main/java/me/ahoo/cosid/converter/DatePrefixIdConverter.java index 84723d9f45..24460fc315 100644 --- a/cosid-core/src/main/java/me/ahoo/cosid/converter/DatePrefixIdConverter.java +++ b/cosid-core/src/main/java/me/ahoo/cosid/converter/DatePrefixIdConverter.java @@ -23,14 +23,12 @@ import java.time.format.DateTimeFormatter; public class DatePrefixIdConverter implements IdConverter, Decorator { - private final String prefix; private final String pattern; private final DateTimeFormatter formatter; private final String delimiter; private final IdConverter actual; - public DatePrefixIdConverter(String prefix, String pattern, String delimiter, IdConverter actual) { - this.prefix = prefix; + public DatePrefixIdConverter(String pattern, String delimiter, IdConverter actual) { this.pattern = pattern; this.formatter = DateTimeFormatter.ofPattern(pattern); this.delimiter = delimiter; @@ -41,12 +39,12 @@ public DatePrefixIdConverter(String prefix, String pattern, String delimiter, Id @Nonnull @Override public String asString(long id) { - return prefix + LocalDateTime.now().format(formatter) + delimiter + actual.asString(id); + return LocalDateTime.now().format(formatter) + delimiter + actual.asString(id); } @Override public long asLong(@Nonnull String idString) { - int appendedLength = prefix.length() + pattern.length() + delimiter.length(); + int appendedLength = pattern.length() + delimiter.length(); String idStr = idString.substring(appendedLength); return actual.asLong(idStr); } @@ -59,6 +57,6 @@ public IdConverter getActual() { @Override public Stat stat() { - return new DatePrefixConverterStat(getClass().getSimpleName(), prefix, formatter.toString(), actual.stat()); + return new DatePrefixConverterStat(getClass().getSimpleName(), pattern, actual.stat()); } } diff --git a/cosid-core/src/main/java/me/ahoo/cosid/stat/converter/DatePrefixConverterStat.java b/cosid-core/src/main/java/me/ahoo/cosid/stat/converter/DatePrefixConverterStat.java index 708dea4084..18daaf9cb3 100644 --- a/cosid-core/src/main/java/me/ahoo/cosid/stat/converter/DatePrefixConverterStat.java +++ b/cosid-core/src/main/java/me/ahoo/cosid/stat/converter/DatePrefixConverterStat.java @@ -15,5 +15,5 @@ import me.ahoo.cosid.stat.Stat; -public record DatePrefixConverterStat(String kind, String prefix, String formatter, Stat actual) implements Stat { +public record DatePrefixConverterStat(String kind, String pattern, Stat actual) implements Stat { } diff --git a/cosid-core/src/test/java/me/ahoo/cosid/converter/DatePrefixIdConverterTest.java b/cosid-core/src/test/java/me/ahoo/cosid/converter/DatePrefixIdConverterTest.java index dd68441af6..ed9c02b048 100644 --- a/cosid-core/src/test/java/me/ahoo/cosid/converter/DatePrefixIdConverterTest.java +++ b/cosid-core/src/test/java/me/ahoo/cosid/converter/DatePrefixIdConverterTest.java @@ -25,19 +25,18 @@ import static org.hamcrest.Matchers.instanceOf; class DatePrefixIdConverterTest { - private static final String PREFIX = "prefix_"; - private final DatePrefixIdConverter idConverter = new DatePrefixIdConverter(PREFIX, "yyMMdd", DEFAULT_DELIMITER, ToStringIdConverter.INSTANCE); + private final DatePrefixIdConverter idConverter = new DatePrefixIdConverter("yyMMdd", DEFAULT_DELIMITER, ToStringIdConverter.INSTANCE); @Test void asString() { String idString = idConverter.asString(1); - String expected = PREFIX + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMdd")) + DEFAULT_DELIMITER + "1"; + String expected = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMdd")) + DEFAULT_DELIMITER + "1"; assertThat(idString, equalTo(expected)); } @Test void asLong() { - assertThat(idConverter.asLong("prefix_240618-1"), equalTo(1L)); + assertThat(idConverter.asLong("240618-1"), equalTo(1L)); } @Test diff --git a/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDecorator.java b/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDecorator.java index 6cd9527829..6eb22f7360 100644 --- a/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDecorator.java +++ b/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDecorator.java @@ -15,6 +15,7 @@ import me.ahoo.cosid.IdConverter; import me.ahoo.cosid.IdGenerator; +import me.ahoo.cosid.converter.DatePrefixIdConverter; import me.ahoo.cosid.converter.PrefixIdConverter; import me.ahoo.cosid.converter.Radix36IdConverter; import me.ahoo.cosid.converter.Radix62IdConverter; @@ -25,16 +26,17 @@ import com.google.common.base.Strings; import java.lang.reflect.InvocationTargetException; +import java.util.Date; public abstract class IdConverterDecorator { protected final T idGenerator; protected final IdConverterDefinition converterDefinition; - + protected IdConverterDecorator(T idGenerator, IdConverterDefinition converterDefinition) { this.idGenerator = idGenerator; this.converterDefinition = converterDefinition; } - + public T decorate() { IdConverter idConverter = ToStringIdConverter.INSTANCE; switch (converterDefinition.getType()) { @@ -45,35 +47,46 @@ public T decorate() { case CUSTOM -> idConverter = newCustom(); default -> throw new IllegalStateException("Unexpected value: " + converterDefinition.getType()); } - + IdConverterDefinition.GroupPrefix groupPrefix = converterDefinition.getGroupPrefix(); - + if (groupPrefix.isEnabled() && groupPrefix.isBeforePrefix()) { idConverter = new GroupedPrefixIdConverter(groupPrefix.getDelimiter(), idConverter); } + + IdConverterDefinition.DatePrefix datePrefix = converterDefinition.getDatePrefix(); + if (datePrefix.isEnabled() && datePrefix.isBeforePrefix()) { + idConverter = new DatePrefixIdConverter(datePrefix.getPattern(), datePrefix.getDelimiter(), idConverter); + } + if (!Strings.isNullOrEmpty(converterDefinition.getPrefix())) { idConverter = new PrefixIdConverter(converterDefinition.getPrefix(), idConverter); } if (groupPrefix.isEnabled() && !groupPrefix.isBeforePrefix()) { idConverter = new GroupedPrefixIdConverter(groupPrefix.getDelimiter(), idConverter); } + + if (datePrefix.isEnabled() && !datePrefix.isBeforePrefix()) { + idConverter = new DatePrefixIdConverter(datePrefix.getPattern(), datePrefix.getDelimiter(), idConverter); + } + if (!Strings.isNullOrEmpty(converterDefinition.getSuffix())) { idConverter = new SuffixIdConverter(converterDefinition.getSuffix(), idConverter); } - + return newIdGenerator(idConverter); } - + protected IdConverter newRadix() { IdConverterDefinition.Radix radix = converterDefinition.getRadix(); return Radix62IdConverter.of(radix.isPadStart(), radix.getCharSize()); } - + protected IdConverter newRadix36() { IdConverterDefinition.Radix36 radix36 = converterDefinition.getRadix36(); return Radix36IdConverter.of(radix36.isPadStart(), radix36.getCharSize()); } - + protected IdConverter newToString(IdConverter defaultIdConverter) { IdConverterDefinition.ToString toString = converterDefinition.getToString(); if (toString != null) { @@ -81,11 +94,11 @@ protected IdConverter newToString(IdConverter defaultIdConverter) { } return defaultIdConverter; } - + protected IdConverter newSnowflakeFriendly() { throw new UnsupportedOperationException("newSnowflakeFriendly"); } - + protected IdConverter newCustom() { IdConverterDefinition.Custom custom = converterDefinition.getCustom(); try { @@ -94,6 +107,6 @@ protected IdConverter newCustom() { throw new RuntimeException(e); } } - + protected abstract T newIdGenerator(IdConverter idConverter); } diff --git a/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDefinition.java b/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDefinition.java index f9e7585fd8..39120522c0 100644 --- a/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDefinition.java +++ b/cosid-spring-boot-starter/src/main/java/me/ahoo/cosid/spring/boot/starter/IdConverterDefinition.java @@ -24,7 +24,7 @@ * @author ahoo wang */ public class IdConverterDefinition { - + private Type type = Type.RADIX; private String prefix; private GroupPrefix groupPrefix = new GroupPrefix(); @@ -33,192 +33,245 @@ public class IdConverterDefinition { private Radix36 radix36 = new Radix36(); private ToString toString; private Custom custom; - + private DatePrefix datePrefix = new DatePrefix(); + public Type getType() { return type; } - + public void setType(Type type) { this.type = type; } - + public String getPrefix() { return prefix; } - + public void setPrefix(String prefix) { this.prefix = prefix; } - + public GroupPrefix getGroupPrefix() { return groupPrefix; } - + public void setGroupPrefix(GroupPrefix groupPrefix) { this.groupPrefix = groupPrefix; } - + public String getSuffix() { return suffix; } - + public void setSuffix(String suffix) { this.suffix = suffix; } - + public Radix getRadix() { return radix; } - + public void setRadix(Radix radix) { this.radix = radix; } - + public Radix36 getRadix36() { return radix36; } - + public void setRadix36(Radix36 radix36) { this.radix36 = radix36; } - + public ToString getToString() { return toString; } - + public void setToString(ToString toString) { this.toString = toString; } - + public Custom getCustom() { return custom; } - + public void setCustom(Custom custom) { this.custom = custom; } - + + public DatePrefix getDatePrefix() { + return datePrefix; + } + + public IdConverterDefinition setDatePrefix(DatePrefix datePrefix) { + this.datePrefix = datePrefix; + return this; + } + /** * Radix62IdConverter Config. */ public static class Radix implements PadStartIdConverter { - + private boolean padStart = true; private int charSize = Radix62IdConverter.MAX_CHAR_SIZE; - + @Override public boolean isPadStart() { return padStart; } - + public void setPadStart(boolean padStart) { this.padStart = padStart; } - + @Override public int getCharSize() { return charSize; } - + public void setCharSize(int charSize) { this.charSize = charSize; } } - + public static class Radix36 implements PadStartIdConverter { - + private boolean padStart = true; private int charSize = Radix36IdConverter.MAX_CHAR_SIZE; - + @Override public boolean isPadStart() { return padStart; } - + public void setPadStart(boolean padStart) { this.padStart = padStart; } - + @Override public int getCharSize() { return charSize; } - + public void setCharSize(int charSize) { this.charSize = charSize; } } - + public static class ToString implements PadStartIdConverter { - + private boolean padStart = false; private int charSize = Radix62IdConverter.MAX_CHAR_SIZE; - + @Override public boolean isPadStart() { return padStart; } - + public void setPadStart(boolean padStart) { this.padStart = padStart; } - + @Override public int getCharSize() { return charSize; } - + public void setCharSize(int charSize) { this.charSize = charSize; } } - + public static class GroupPrefix { private boolean enabled = false; private String delimiter = GroupedPrefixIdConverter.DEFAULT_DELIMITER; private boolean beforePrefix = true; - + public boolean isEnabled() { return enabled; } - + public GroupPrefix setEnabled(boolean enabled) { this.enabled = enabled; return this; } - + public String getDelimiter() { return delimiter; } - + public GroupPrefix setDelimiter(String delimiter) { this.delimiter = delimiter; return this; } - + public boolean isBeforePrefix() { return beforePrefix; } - + public GroupPrefix setBeforePrefix(boolean beforePrefix) { this.beforePrefix = beforePrefix; return this; } } - + + public static class DatePrefix { + private boolean enabled = false; + private String delimiter = GroupedPrefixIdConverter.DEFAULT_DELIMITER; + private String pattern = "yyMMdd"; + private boolean beforePrefix = true; + + public boolean isEnabled() { + return enabled; + } + + public DatePrefix setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public String getDelimiter() { + return delimiter; + } + + public DatePrefix setDelimiter(String delimiter) { + this.delimiter = delimiter; + return this; + } + + public String getPattern() { + return pattern; + } + + public DatePrefix setPattern(String pattern) { + this.pattern = pattern; + return this; + } + + public boolean isBeforePrefix() { + return beforePrefix; + } + + public DatePrefix setBeforePrefix(boolean beforePrefix) { + this.beforePrefix = beforePrefix; + return this; + } + } + public static class Custom { private Class type; - + public Class getType() { return type; } - + public Custom setType(Class type) { this.type = type; return this; } } - + /** * IdConverter Type. */ @@ -229,10 +282,10 @@ public enum Type { RADIX36, CUSTOM } - + interface PadStartIdConverter { boolean isPadStart(); - + int getCharSize(); } } diff --git a/cosid-spring-boot-starter/src/test/java/me/ahoo/cosid/spring/boot/starter/segment/SegmentIdConverterDecoratorTest.java b/cosid-spring-boot-starter/src/test/java/me/ahoo/cosid/spring/boot/starter/segment/SegmentIdConverterDecoratorTest.java index 92e245ee45..7dfc6aacaf 100644 --- a/cosid-spring-boot-starter/src/test/java/me/ahoo/cosid/spring/boot/starter/segment/SegmentIdConverterDecoratorTest.java +++ b/cosid-spring-boot-starter/src/test/java/me/ahoo/cosid/spring/boot/starter/segment/SegmentIdConverterDecoratorTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.*; import me.ahoo.cosid.IdConverter; +import me.ahoo.cosid.converter.DatePrefixIdConverter; import me.ahoo.cosid.converter.SuffixIdConverter; import me.ahoo.cosid.converter.GroupedPrefixIdConverter; import me.ahoo.cosid.segment.DefaultSegmentId; @@ -36,10 +37,10 @@ void newSnowflakeFriendly() { idConverterDefinition.setType(IdConverterDefinition.Type.SNOWFLAKE_FRIENDLY); SegmentId segmentId = new DefaultSegmentId(new IdSegmentDistributor.Mock()); Assertions.assertThrows(UnsupportedOperationException.class, - () -> new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate() + () -> new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate() ); } - + @Test void newCustom() { IdConverterDefinition idConverterDefinition = new IdConverterDefinition(); @@ -49,8 +50,8 @@ void newCustom() { SegmentId newIdGen = new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate(); assertThat(newIdGen.idConverter(), instanceOf(SegmentIdConverterDecoratorTest.CustomIdConverter.class)); } - - + + @Test void withPrefixAndSuffix() { IdConverterDefinition idConverterDefinition = new IdConverterDefinition(); @@ -60,7 +61,7 @@ void withPrefixAndSuffix() { SegmentId newIdGen = new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate(); assertThat(newIdGen.idConverter(), instanceOf(SuffixIdConverter.class)); } - + @Test void withGroupPrefix() { IdConverterDefinition idConverterDefinition = new IdConverterDefinition(); @@ -69,7 +70,7 @@ void withGroupPrefix() { SegmentId newIdGen = new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate(); assertThat(newIdGen.idConverter(), instanceOf(GroupedPrefixIdConverter.class)); } - + @Test void withYearPrefixAfterPrefix() { IdConverterDefinition idConverterDefinition = new IdConverterDefinition(); @@ -79,14 +80,32 @@ void withYearPrefixAfterPrefix() { SegmentId newIdGen = new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate(); assertThat(newIdGen.idConverter(), instanceOf(GroupedPrefixIdConverter.class)); } - + + @Test + void withDatePrefix() { + IdConverterDefinition idConverterDefinition = new IdConverterDefinition(); + idConverterDefinition.setDatePrefix(new IdConverterDefinition.DatePrefix().setEnabled(true)); + SegmentId segmentId = new DefaultSegmentId(new IdSegmentDistributor.Mock()); + SegmentId newIdGen = new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate(); + assertThat(newIdGen.idConverter(), instanceOf(DatePrefixIdConverter.class)); + } + + @Test + void withDateNotBeforePrefix() { + IdConverterDefinition idConverterDefinition = new IdConverterDefinition(); + idConverterDefinition.setDatePrefix(new IdConverterDefinition.DatePrefix().setEnabled(true).setBeforePrefix(false)); + SegmentId segmentId = new DefaultSegmentId(new IdSegmentDistributor.Mock()); + SegmentId newIdGen = new SegmentIdConverterDecorator(segmentId, idConverterDefinition).decorate(); + assertThat(newIdGen.idConverter(), instanceOf(DatePrefixIdConverter.class)); + } + public static class CustomIdConverter implements IdConverter { @Nonnull @Override public String asString(long id) { return String.valueOf(id); } - + @Override public long asLong(@Nonnull String idString) { return Long.getLong(idString); diff --git a/examples/cosid-example-redis/src/main/resources/application.yaml b/examples/cosid-example-redis/src/main/resources/application.yaml index dc9a39b0e3..e8124fd5a0 100644 --- a/examples/cosid-example-redis/src/main/resources/application.yaml +++ b/examples/cosid-example-redis/src/main/resources/application.yaml @@ -62,6 +62,16 @@ cosid: to-string: char-size: 10 pad-start: true + date_prefix_no: + offset: 2000000000 + converter: + type: to_string + to-string: + char-size: 10 + pad-start: true + prefix: BIZ- + date-prefix: + enabled: true no_suffix_biz: offset: 2000000000 converter: