Skip to content

Commit 1cdb588

Browse files
committed
refactor(templates): extract the identity layer to templates.core.identity
Introduce a family-neutral PartyIdentity contract (displayName / tagline / contact / links) in com.demcha.compose.document.templates.core.identity and move the shared header widgets (Headline, ContactLine, Masthead, Subheadline, SvgGlyph) plus the Contact (was CvContact) and Link (was CvLink) records there. Headline now renders a String name and ContactLine / Masthead accept a PartyIdentity, so any family can reuse them. CvName and CvIdentity stay in cv.v2.data, with CvIdentity implementing PartyIdentity, so most call sites are unchanged (a CvIdentity is a PartyIdentity); Headline callers pass name().full(). Render is byte-identical (1607 tests, zero snapshot updates); the move is a deliberate binary break on the 2.0 line (japicmp report-only). Markdown docs follow in the docs refresh.
1 parent dfcae82 commit 1cdb588

50 files changed

Lines changed: 292 additions & 175 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvContact.java renamed to src/main/java/com/demcha/compose/document/templates/core/identity/Contact.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.demcha.compose.document.templates.cv.v2.data;
1+
package com.demcha.compose.document.templates.core.identity;
22

33
import java.util.Objects;
44

@@ -13,12 +13,12 @@
1313
* @param email non-blank email (rendered as a clickable mailto link)
1414
* @param address non-blank location / postal address line
1515
*/
16-
public record CvContact(String phone, String email, String address) {
16+
public record Contact(String phone, String email, String address) {
1717

1818
/**
1919
* Validates that every field is non-null and non-blank.
2020
*/
21-
public CvContact {
21+
public Contact {
2222
Objects.requireNonNull(phone, "phone");
2323
Objects.requireNonNull(email, "email");
2424
Objects.requireNonNull(address, "address");

src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/ContactLine.java renamed to src/main/java/com/demcha/compose/document/templates/core/identity/ContactLine.java

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
package com.demcha.compose.document.templates.cv.v2.widgets;
1+
package com.demcha.compose.document.templates.core.identity;
22

33
import com.demcha.compose.document.dsl.SectionBuilder;
44
import com.demcha.compose.document.node.DocumentLinkOptions;
55
import com.demcha.compose.document.node.TextAlign;
66
import com.demcha.compose.document.style.DocumentInsets;
77
import com.demcha.compose.document.style.DocumentTextStyle;
8-
import com.demcha.compose.document.templates.cv.v2.data.CvContact;
9-
import com.demcha.compose.document.templates.cv.v2.data.CvIdentity;
10-
import com.demcha.compose.document.templates.cv.v2.data.CvLink;
8+
import com.demcha.compose.document.templates.core.identity.Contact;
9+
import com.demcha.compose.document.templates.core.identity.Link;
1110
import com.demcha.compose.document.templates.core.theme.BrandTheme;
1211

1312
import java.util.ArrayList;
@@ -34,7 +33,7 @@
3433
* </ul>
3534
*
3635
* <p>Email is always rendered as a clickable {@code mailto:} link;
37-
* each optional {@link CvLink} becomes a clickable hyperlink with
36+
* each optional {@link Link} becomes a clickable hyperlink with
3837
* the {@code label} as the visible text. The separator glyph comes
3938
* from {@code theme.decoration().contactSeparator()}.</p>
4039
*/
@@ -52,14 +51,14 @@ private ContactLine() {
5251
* @param identity the CV identity supplying contact fields and links
5352
* @param theme the active theme supplying palette, typography, and spacing
5453
*/
55-
public static void centered(SectionBuilder host, CvIdentity identity, BrandTheme theme) {
54+
public static void centered(SectionBuilder host, PartyIdentity identity, BrandTheme theme) {
5655
render(host, identity, theme, TextAlign.CENTER, Order.PHONE_FIRST);
5756
}
5857

5958
/**
6059
* Centred contact row with explicit text-style overrides for
6160
* non-link text, clickable links, and separators. Same ordering as
62-
* {@link #centered(SectionBuilder, CvIdentity, BrandTheme)}, but lets
61+
* {@link #centered(SectionBuilder, PartyIdentity, BrandTheme)}, but lets
6362
* editorial presets tint / underline the links without forking the
6463
* contact assembly logic.
6564
*
@@ -76,7 +75,7 @@ public static void centered(SectionBuilder host, CvIdentity identity, BrandTheme
7675
* {@code null} →
7776
* {@code theme.contactSeparatorStyle()}
7877
*/
79-
public static void centered(SectionBuilder host, CvIdentity identity,
78+
public static void centered(SectionBuilder host, PartyIdentity identity,
8079
BrandTheme theme,
8180
DocumentTextStyle bodyStyleOverride,
8281
DocumentTextStyle linkStyleOverride,
@@ -94,7 +93,7 @@ public static void centered(SectionBuilder host, CvIdentity identity,
9493
* @param identity the CV identity supplying contact fields and links
9594
* @param theme the active theme supplying palette, typography, and spacing
9695
*/
97-
public static void rightAligned(SectionBuilder host, CvIdentity identity, BrandTheme theme) {
96+
public static void rightAligned(SectionBuilder host, PartyIdentity identity, BrandTheme theme) {
9897
render(host, identity, theme, TextAlign.RIGHT, Order.ADDRESS_FIRST);
9998
}
10099

@@ -107,7 +106,7 @@ public static void rightAligned(SectionBuilder host, CvIdentity identity, BrandT
107106
* @param identity the CV identity supplying contact fields and links
108107
* @param theme the active theme supplying palette, typography, and spacing
109108
*/
110-
public static void leftAligned(SectionBuilder host, CvIdentity identity,
109+
public static void leftAligned(SectionBuilder host, PartyIdentity identity,
111110
BrandTheme theme) {
112111
render(host, identity, theme, TextAlign.LEFT, Order.ADDRESS_FIRST);
113112
}
@@ -129,7 +128,7 @@ public static void leftAligned(SectionBuilder host, CvIdentity identity,
129128
* {@code null} ->
130129
* {@code theme.contactSeparatorStyle()}
131130
*/
132-
public static void leftAligned(SectionBuilder host, CvIdentity identity,
131+
public static void leftAligned(SectionBuilder host, PartyIdentity identity,
133132
BrandTheme theme,
134133
DocumentTextStyle bodyStyleOverride,
135134
DocumentTextStyle linkStyleOverride,
@@ -151,7 +150,7 @@ public static void leftAligned(SectionBuilder host, CvIdentity identity,
151150
* <li><strong>Row 2</strong> — email {@code |} link₁ {@code |} link₂ … (all clickable)</li>
152151
* </ul>
153152
*
154-
* <p>Email and every {@link CvLink} are rendered as proper PDF
153+
* <p>Email and every {@link Link} are rendered as proper PDF
155154
* hyperlinks (mailto: for the email, the link's URL for each
156155
* label) — not just styled text.</p>
157156
*
@@ -168,7 +167,7 @@ public static void leftAligned(SectionBuilder host, CvIdentity identity,
168167
* separator; {@code null} →
169168
* {@code theme.contactSeparatorStyle()}
170169
*/
171-
public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity,
170+
public static void twoRowRightAligned(SectionBuilder host, PartyIdentity identity,
172171
BrandTheme theme,
173172
DocumentTextStyle bodyStyleOverride,
174173
DocumentTextStyle linkStyleOverride,
@@ -180,7 +179,7 @@ public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity,
180179
DocumentTextStyle separatorStyle = separatorStyleOverride != null
181180
? separatorStyleOverride : theme.contactSeparatorStyle();
182181

183-
CvContact c = identity.contact();
182+
Contact c = identity.contact();
184183
host.spacing(0).padding(theme.spacing().contactPadding())
185184
// Row 1 — address + phone.
186185
.addParagraph(p -> p
@@ -200,7 +199,7 @@ public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity,
200199
.rich(rich -> {
201200
rich.with(c.email(), linkStyle,
202201
new DocumentLinkOptions("mailto:" + c.email()));
203-
for (CvLink l : identity.links()) {
202+
for (Link l : identity.links()) {
204203
rich.style(" | ", separatorStyle);
205204
rich.with(l.label(), linkStyle,
206205
new DocumentLinkOptions(l.url()));
@@ -218,7 +217,7 @@ public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity,
218217
* @param theme the active theme supplying palette, typography, and spacing
219218
*/
220219
public static void rightAlignedStacked(SectionBuilder host,
221-
CvIdentity identity,
220+
PartyIdentity identity,
222221
BrandTheme theme) {
223222
rightAlignedStacked(host, identity, theme, null, null);
224223
}
@@ -236,7 +235,7 @@ public static void rightAlignedStacked(SectionBuilder host,
236235
* → resolved body style
237236
*/
238237
public static void rightAlignedStacked(SectionBuilder host,
239-
CvIdentity identity,
238+
PartyIdentity identity,
240239
BrandTheme theme,
241240
DocumentTextStyle bodyStyleOverride,
242241
DocumentTextStyle linkStyleOverride) {
@@ -274,7 +273,7 @@ public static void rightAlignedStacked(SectionBuilder host,
274273
* @param alignment horizontal text alignment for the row
275274
* @param order the field order in the rendered line
276275
*/
277-
public static void render(SectionBuilder host, CvIdentity identity, BrandTheme theme,
276+
public static void render(SectionBuilder host, PartyIdentity identity, BrandTheme theme,
278277
TextAlign alignment, Order order) {
279278
List<Part> parts = parts(identity, order);
280279
DocumentTextStyle textStyle = theme.contactStyle();
@@ -302,7 +301,7 @@ public static void render(SectionBuilder host, CvIdentity identity, BrandTheme t
302301
}));
303302
}
304303

305-
private static void renderStyled(SectionBuilder host, CvIdentity identity,
304+
private static void renderStyled(SectionBuilder host, PartyIdentity identity,
306305
BrandTheme theme, TextAlign alignment,
307306
Order order,
308307
DocumentTextStyle bodyStyleOverride,
@@ -352,8 +351,8 @@ public enum Order {
352351
ADDRESS_FIRST
353352
}
354353

355-
private static List<Part> parts(CvIdentity identity, Order order) {
356-
CvContact c = identity.contact();
354+
private static List<Part> parts(PartyIdentity identity, Order order) {
355+
Contact c = identity.contact();
357356
List<Part> parts = new ArrayList<>(4 + identity.links().size());
358357
DocumentLinkOptions email = new DocumentLinkOptions("mailto:" + c.email());
359358
switch (order) {
@@ -368,7 +367,7 @@ private static List<Part> parts(CvIdentity identity, Order order) {
368367
parts.add(new Part(c.email(), email));
369368
}
370369
}
371-
for (CvLink link : identity.links()) {
370+
for (Link link : identity.links()) {
372371
parts.add(new Part(link.label(), new DocumentLinkOptions(link.url())));
373372
}
374373
return parts;

src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Headline.java renamed to src/main/java/com/demcha/compose/document/templates/core/identity/Headline.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
package com.demcha.compose.document.templates.cv.v2.widgets;
1+
package com.demcha.compose.document.templates.core.identity;
22

33
import com.demcha.compose.document.dsl.SectionBuilder;
44
import com.demcha.compose.document.node.TextAlign;
55
import com.demcha.compose.document.style.DocumentInsets;
66
import com.demcha.compose.document.style.DocumentTextStyle;
77
import com.demcha.compose.document.templates.core.text.TextOrnaments;
8-
import com.demcha.compose.document.templates.cv.v2.data.CvName;
98
import com.demcha.compose.document.templates.core.theme.BrandTheme;
109

1110
/**
@@ -55,7 +54,7 @@ private Headline() {
5554
* @param name name to render
5655
* @param theme the active theme supplying palette, typography, and spacing
5756
*/
58-
public static void spacedCentered(SectionBuilder host, CvName name, BrandTheme theme) {
57+
public static void spacedCentered(SectionBuilder host, String name, BrandTheme theme) {
5958
render(host, name, theme, TextAlign.CENTER, true);
6059
}
6160

@@ -68,7 +67,7 @@ public static void spacedCentered(SectionBuilder host, CvName name, BrandTheme t
6867
* @param name name to render
6968
* @param theme the active theme supplying palette, typography, and spacing
7069
*/
71-
public static void uppercaseCentered(SectionBuilder host, CvName name,
70+
public static void uppercaseCentered(SectionBuilder host, String name,
7271
BrandTheme theme) {
7372
uppercaseCentered(host, name, theme, null);
7473
}
@@ -83,10 +82,10 @@ public static void uppercaseCentered(SectionBuilder host, CvName name,
8382
* @param styleOverride explicit style; pass {@code null} to fall
8483
* back to {@code theme.headlineStyle()}
8584
*/
86-
public static void uppercaseCentered(SectionBuilder host, CvName name,
85+
public static void uppercaseCentered(SectionBuilder host, String name,
8786
BrandTheme theme,
8887
DocumentTextStyle styleOverride) {
89-
renderText(host, name.full().toUpperCase(java.util.Locale.ROOT),
88+
renderText(host, name.toUpperCase(java.util.Locale.ROOT),
9089
theme, TextAlign.CENTER, styleOverride);
9190
}
9291

@@ -99,7 +98,7 @@ public static void uppercaseCentered(SectionBuilder host, CvName name,
9998
* @param name name to render
10099
* @param theme the active theme supplying palette, typography, and spacing
101100
*/
102-
public static void uppercaseLeftAligned(SectionBuilder host, CvName name,
101+
public static void uppercaseLeftAligned(SectionBuilder host, String name,
103102
BrandTheme theme) {
104103
uppercaseLeftAligned(host, name, theme, null);
105104
}
@@ -114,10 +113,10 @@ public static void uppercaseLeftAligned(SectionBuilder host, CvName name,
114113
* @param styleOverride explicit style; pass {@code null} to fall
115114
* back to {@code theme.headlineStyle()}
116115
*/
117-
public static void uppercaseLeftAligned(SectionBuilder host, CvName name,
116+
public static void uppercaseLeftAligned(SectionBuilder host, String name,
118117
BrandTheme theme,
119118
DocumentTextStyle styleOverride) {
120-
renderText(host, name.full().toUpperCase(java.util.Locale.ROOT),
119+
renderText(host, name.toUpperCase(java.util.Locale.ROOT),
121120
theme, TextAlign.LEFT, styleOverride);
122121
}
123122

@@ -131,7 +130,7 @@ public static void uppercaseLeftAligned(SectionBuilder host, CvName name,
131130
* @param name name to render
132131
* @param theme the active theme supplying palette, typography, and spacing
133132
*/
134-
public static void rightAligned(SectionBuilder host, CvName name, BrandTheme theme) {
133+
public static void rightAligned(SectionBuilder host, String name, BrandTheme theme) {
135134
rightAligned(host, name, theme, null);
136135
}
137136

@@ -147,7 +146,7 @@ public static void rightAligned(SectionBuilder host, CvName name, BrandTheme the
147146
* @param styleOverride text style for the headline; pass {@code null}
148147
* to fall back to {@code theme.headlineStyle()}
149148
*/
150-
public static void rightAligned(SectionBuilder host, CvName name, BrandTheme theme,
149+
public static void rightAligned(SectionBuilder host, String name, BrandTheme theme,
151150
DocumentTextStyle styleOverride) {
152151
render(host, name, theme, TextAlign.RIGHT, false, styleOverride);
153152
}
@@ -165,14 +164,14 @@ public static void rightAligned(SectionBuilder host, CvName name, BrandTheme the
165164
* @param spacedCaps if true, transforms to letter-spaced
166165
* uppercase; if false, renders verbatim
167166
*/
168-
public static void render(SectionBuilder host, CvName name, BrandTheme theme,
167+
public static void render(SectionBuilder host, String name, BrandTheme theme,
169168
TextAlign alignment, boolean spacedCaps) {
170169
render(host, name, theme, alignment, spacedCaps, null);
171170
}
172171

173172
/**
174173
* Lower-level entry with explicit style override. Same shape as
175-
* the 5-arg {@link #render(SectionBuilder, CvName, BrandTheme, TextAlign, boolean)}
174+
* the 5-arg {@link #render(SectionBuilder, String, BrandTheme, TextAlign, boolean)}
176175
* but lets the caller supply a custom {@link DocumentTextStyle}.
177176
*
178177
* @param host host section
@@ -184,15 +183,15 @@ public static void render(SectionBuilder host, CvName name, BrandTheme theme,
184183
* @param styleOverride explicit style; pass {@code null} to fall
185184
* back to {@code theme.headlineStyle()}
186185
*/
187-
public static void render(SectionBuilder host, CvName name, BrandTheme theme,
186+
public static void render(SectionBuilder host, String name, BrandTheme theme,
188187
TextAlign alignment, boolean spacedCaps,
189188
DocumentTextStyle styleOverride) {
190189
DocumentTextStyle style = styleOverride != null
191190
? styleOverride
192191
: theme.headlineStyle();
193192
String text = spacedCaps
194-
? TextOrnaments.spacedUpper(name.full())
195-
: name.full();
193+
? TextOrnaments.spacedUpper(name)
194+
: name;
196195

197196
renderText(host, text, theme, alignment, style);
198197
}

src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvLink.java renamed to src/main/java/com/demcha/compose/document/templates/core/identity/Link.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.demcha.compose.document.templates.cv.v2.data;
1+
package com.demcha.compose.document.templates.core.identity;
22

33
import java.util.Objects;
44

@@ -9,12 +9,12 @@
99
* @param label visible link text (required, non-blank)
1010
* @param url click target (required, non-blank)
1111
*/
12-
public record CvLink(String label, String url) {
12+
public record Link(String label, String url) {
1313

1414
/**
1515
* Validates that both fields are non-null and non-blank.
1616
*/
17-
public CvLink {
17+
public Link {
1818
Objects.requireNonNull(label, "label");
1919
Objects.requireNonNull(url, "url");
2020
if (label.isBlank()) {
@@ -26,14 +26,14 @@ public record CvLink(String label, String url) {
2626
}
2727

2828
/**
29-
* Convenience factory mirroring {@code CvLink.of("LinkedIn",
29+
* Convenience factory mirroring {@code Link.of("LinkedIn",
3030
* "https://...")} call sites.
3131
*
3232
* @param label visible link text (required, non-blank)
3333
* @param url click target (required, non-blank)
34-
* @return a {@code CvLink} with the given label and target
34+
* @return a {@code Link} with the given label and target
3535
*/
36-
public static CvLink of(String label, String url) {
37-
return new CvLink(label, url);
36+
public static Link of(String label, String url) {
37+
return new Link(label, url);
3838
}
3939
}

0 commit comments

Comments
 (0)