Bump dawidd6/action-send-mail from 3 to 4
[yosql.git] / yosql-models / yosql-models-configuration / src / main / java / wtf / metio / yosql / models / configuration / Annotation.java
blob7fe43787e9232c0009563c469ba7ebb348b3caaf
1 /*
2 * This file is part of yosql. It is subject to the license terms in the LICENSE file found in the top-level
3 * directory of this distribution and at https://creativecommons.org/publicdomain/zero/1.0/. No part of yosql,
4 * including this file, may be copied, modified, propagated, or distributed except according to the terms contained
5 * in the LICENSE file.
6 */
7 package wtf.metio.yosql.models.configuration;
9 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
10 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
11 import org.immutables.value.Value;
12 import wtf.metio.yosql.internals.jdk.Buckets;
13 import wtf.metio.yosql.internals.jdk.Strings;
15 import java.util.Arrays;
16 import java.util.List;
17 import java.util.Optional;
18 import java.util.function.Predicate;
19 import java.util.stream.Collectors;
20 import java.util.stream.Stream;
22 /**
23 * Configuration for an extra annotation that is to be placed on a constructor or method in generated code.
25 @Value.Immutable
26 @JsonSerialize(
27 as = ImmutableAnnotation.class
29 @JsonDeserialize(
30 as = ImmutableAnnotation.class
32 public interface Annotation {
34 //region builders
36 static ImmutableAnnotation.TypeBuildStage builder() {
37 return ImmutableAnnotation.builder();
40 static ImmutableAnnotation copyOf(final Annotation annotation) {
41 return ImmutableAnnotation.copyOf(annotation);
44 static Annotation fromString(final String input) {
45 return Optional.ofNullable(input)
46 .map(String::strip)
47 .filter(Predicate.not(Strings::isBlank))
48 .map(value -> value.split(":"))
49 .filter(values -> values.length > 0)
50 .map(values -> Annotation.builder()
51 .setType(values[0])
52 .addAllMembers(parseMembers(values.length > 1 ? Arrays.copyOfRange(values, 1, values.length) : new String[]{}))
53 .build())
54 .orElse(null);
57 private static List<? extends AnnotationMember> parseMembers(final String[] input) {
58 return Arrays.stream(input)
59 .map(String::strip)
60 .filter(Predicate.not(Strings::isBlank))
61 .map(value -> value.split("\\|"))
62 .filter(values -> values.length > 1)
63 .map(values -> AnnotationMember.builder()
64 .setKey(values[0])
65 .setValue(values[1])
66 .setType(values.length > 2 ? values[2] : "java.lang.String")
67 .build())
68 .toList();
71 //endregion
73 //region utils
75 static List<Annotation> mergeAnnotations(
76 final List<Annotation> first,
77 final List<Annotation> second) {
78 if (first == null || first.isEmpty()) {
79 return second;
81 return Stream.concat(copyAttributes(first, second), copyAttributes(second, first))
82 .filter(Buckets.distinctByKey(Annotation::type))
83 .collect(Collectors.toList());
86 private static Stream<ImmutableAnnotation> copyAttributes(
87 final List<Annotation> first,
88 final List<Annotation> second) {
89 return first.stream()
90 .map(annotation -> second.stream()
91 .filter(other -> annotation.type().equals(other.type()))
92 .findFirst()
93 .map(other -> Annotation.copyOf(annotation)
94 .withMembers(mergeMembers(annotation.members(), other.members())))
95 .orElseGet(() -> Annotation.copyOf(annotation)));
98 private static List<AnnotationMember> mergeMembers(
99 final List<AnnotationMember> first,
100 final List<AnnotationMember> second) {
101 if (first == null || first.isEmpty()) {
102 return second;
104 return Stream.concat(first.stream(), second.stream())
105 .filter(Buckets.distinctByKey(AnnotationMember::key))
106 .collect(Collectors.toList());
109 //endregion
112 * @return The fully-qualified type name of this annotation.
114 String type();
117 * @return The members of this annotation.
119 List<AnnotationMember> members();