Skip to content

Commit d76f040

Browse files
Enhance documentation for various interfaces with detailed descriptions and usage examples
1 parent a088f13 commit d76f040

File tree

17 files changed

+1235
-23
lines changed

17 files changed

+1235
-23
lines changed

platform/core/domain/src/main/java/tools/dynamia/domain/AuditableWithJavaTimes.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,65 @@
2020
import java.time.LocalDateTime;
2121
import java.time.LocalTime;
2222

23-
23+
/**
24+
* Interface for entities that require audit tracking using Java 8+ date/time types.
25+
* <p>
26+
* This interface extends the auditing capabilities by separating date and time components using
27+
* {@link LocalDate} and {@link LocalTime} instead of legacy {@link java.util.Date}. It tracks
28+
* when entities are created and last modified, along with optional user information.
29+
* </p>
30+
*
31+
* <p>
32+
* <b>Key features:</b>
33+
* <ul>
34+
* <li>Tracks creation and last update timestamps using modern Java time API</li>
35+
* <li>Separates date and time components for flexible querying and display</li>
36+
* <li>Optional tracking of user who created or last modified the entity</li>
37+
* <li>Provides convenient method to get combined creation date-time</li>
38+
* <li>Improves upon legacy {@link Auditable} interface with modern types</li>
39+
* </ul>
40+
* </p>
41+
*
42+
* <p>
43+
* <b>Usage example:</b>
44+
* <pre>{@code
45+
* @Entity
46+
* public class Document implements AuditableWithJavaTimes {
47+
*
48+
* @Column
49+
* private LocalDate creationDate;
50+
*
51+
* @Column
52+
* private LocalTime creationTime;
53+
*
54+
* @Column
55+
* private LocalDate lastUpdate;
56+
*
57+
* @Column
58+
* private String creator;
59+
*
60+
* // Implement getters and setters
61+
*
62+
* @PrePersist
63+
* protected void onCreate() {
64+
* setCreationDate(LocalDate.now());
65+
* setCreationTime(LocalTime.now());
66+
* }
67+
*
68+
* @PreUpdate
69+
* protected void onUpdate() {
70+
* setLastUpdate(LocalDate.now());
71+
* }
72+
* }
73+
* }</pre>
74+
* </p>
75+
*
76+
* @author Mario A. Serrano Leones
77+
* @see Auditable
78+
* @see LocalDate
79+
* @see LocalTime
80+
* @see LocalDateTime
81+
*/
2482
public interface AuditableWithJavaTimes {
2583

2684
/**

platform/core/domain/src/main/java/tools/dynamia/domain/OpenPersistenceInViewProvider.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,118 @@
1717

1818
package tools.dynamia.domain;
1919

20+
/**
21+
* Interface for implementing the Open Session in View (OSIV) pattern provider.
22+
* <p>
23+
* This interface defines the contract for managing persistence context lifecycle across view rendering,
24+
* commonly known as the "Open Session in View" or "Open EntityManager in View" pattern. It ensures that
25+
* lazy-loaded entities remain accessible during view rendering by keeping the persistence context open
26+
* beyond the service layer.
27+
* </p>
28+
*
29+
* <p>
30+
* <b>Key responsibilities:</b>
31+
* <ul>
32+
* <li>Open persistence context before view rendering</li>
33+
* <li>Close persistence context after view rendering completes</li>
34+
* <li>Handle transaction boundaries for view layer operations</li>
35+
* <li>Manage nested or concurrent view rendering scenarios</li>
36+
* <li>Provide mechanism to disable OSIV when needed</li>
37+
* </ul>
38+
* </p>
39+
*
40+
* <p>
41+
* <b>Pattern flow:</b>
42+
* <ol>
43+
* <li>{@link #beforeView()} is called before rendering begins</li>
44+
* <li>View rendering occurs with open persistence context</li>
45+
* <li>{@link #afterView(boolean)} is called after rendering completes</li>
46+
* <li>{@link #isDisabled()} can be checked to skip OSIV processing</li>
47+
* </ol>
48+
* </p>
49+
*
50+
* <p>
51+
* <b>Usage example:</b>
52+
* <pre>{@code
53+
* @Component
54+
* public class JpaOpenPersistenceInViewProvider implements OpenPersistenceInViewProvider {
55+
*
56+
* @Autowired
57+
* private EntityManagerFactory emf;
58+
*
59+
* private ThreadLocal<EntityManager> contextHolder = new ThreadLocal<>();
60+
*
61+
* @Override
62+
* public boolean beforeView() {
63+
* if (contextHolder.get() != null) {
64+
* return false; // Already participating
65+
* }
66+
* EntityManager em = emf.createEntityManager();
67+
* contextHolder.set(em);
68+
* return true;
69+
* }
70+
*
71+
* @Override
72+
* public void afterView(boolean participate) {
73+
* if (participate) {
74+
* EntityManager em = contextHolder.get();
75+
* if (em != null) {
76+
* em.close();
77+
* contextHolder.remove();
78+
* }
79+
* }
80+
* }
81+
*
82+
* @Override
83+
* public boolean isDisabled() {
84+
* return false; // Enable OSIV
85+
* }
86+
* }
87+
* }</pre>
88+
* </p>
89+
*
90+
* <p>
91+
* <b>Note:</b> While OSIV is convenient for avoiding {@code LazyInitializationException}, it should be used
92+
* carefully as it can lead to performance issues and unexpected database queries in the view layer.
93+
* </p>
94+
*
95+
* @author Mario A. Serrano Leones
96+
*/
2097
public interface OpenPersistenceInViewProvider {
98+
99+
/**
100+
* Called before view rendering begins to open the persistence context.
101+
* <p>
102+
* Implementations should open a new persistence session/context if one doesn't already exist
103+
* for the current thread or request. This method should return {@code true} if a new context
104+
* was opened, or {@code false} if already participating in an existing context.
105+
* </p>
106+
*
107+
* @return {@code true} if a new persistence context was opened, {@code false} if already participating
108+
*/
21109
boolean beforeView();
22110

111+
/**
112+
* Called after view rendering completes to close the persistence context.
113+
* <p>
114+
* Implementations should close the persistence context only if this provider opened it
115+
* (i.e., {@code participate} is {@code true}). This ensures proper cleanup without interfering
116+
* with nested or concurrent view rendering.
117+
* </p>
118+
*
119+
* @param participate {@code true} if this provider opened the context in {@link #beforeView()},
120+
* {@code false} if it was already open
121+
*/
23122
void afterView(boolean participate);
24123

124+
/**
125+
* Checks whether the Open Session in View pattern is disabled.
126+
* <p>
127+
* When this method returns {@code true}, the OSIV mechanism is skipped entirely, and
128+
* persistence context management follows standard service-layer boundaries.
129+
* </p>
130+
*
131+
* @return {@code true} if OSIV is disabled, {@code false} otherwise
132+
*/
25133
boolean isDisabled();
26134
}

platform/core/domain/src/main/java/tools/dynamia/domain/fx/FunctionProvider.java

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,87 @@
1717

1818
package tools.dynamia.domain.fx;
1919

20+
/**
21+
* Interface for providing named functions that can be executed dynamically within the framework.
22+
* <p>
23+
* This interface allows components to expose reusable functions or expressions that can be evaluated
24+
* at runtime. Functions can represent business logic, calculations, queries, scripts, or any other
25+
* executable code that needs to be referenced by name. This is particularly useful for dynamic
26+
* behavior, plugin architectures, rule engines, and expression evaluation systems.
27+
* </p>
28+
*
29+
* <p>
30+
* <b>Key use cases:</b>
31+
* <ul>
32+
* <li>Dynamic field calculations and computed properties</li>
33+
* <li>Business rule definitions and validation logic</li>
34+
* <li>Query builders and filter expressions</li>
35+
* <li>Scripting and formula evaluation</li>
36+
* <li>Plugin-based extensibility</li>
37+
* </ul>
38+
* </p>
39+
*
40+
* <p>
41+
* <b>Usage example:</b>
42+
* <pre>{@code
43+
* @Component
44+
* public class TaxCalculationFunction implements FunctionProvider {
45+
*
46+
* @Override
47+
* public String getName() {
48+
* return "calculateTax";
49+
* }
50+
*
51+
* @Override
52+
* public String getFunction() {
53+
* return "amount * 0.19"; // 19% tax formula
54+
* }
55+
* }
56+
*
57+
* // Or for SQL functions
58+
* @Component
59+
* public class FullNameFunction implements FunctionProvider {
60+
*
61+
* @Override
62+
* public String getName() {
63+
* return "fullName";
64+
* }
65+
*
66+
* @Override
67+
* public String getFunction() {
68+
* return "CONCAT(firstName, ' ', lastName)";
69+
* }
70+
* }
71+
* }</pre>
72+
* </p>
73+
*
74+
* @author Mario A. Serrano Leones
75+
* @see Function
76+
* @see MultiFunctionProcessor
77+
*/
2078
public interface FunctionProvider {
2179

22-
80+
/**
81+
* Returns the unique name of this function.
82+
* <p>
83+
* The name is used to identify and reference the function within the system. It should be
84+
* unique, descriptive, and follow naming conventions (e.g., camelCase or snake_case).
85+
* </p>
86+
*
87+
* @return the function name
88+
*/
2389
String getName();
2490

91+
/**
92+
* Returns the function definition, expression, or implementation code.
93+
* <p>
94+
* The returned string can be a formula, expression, SQL snippet, script code, or any other
95+
* representation of the function logic. The format depends on how the function will be
96+
* processed by the function processor or evaluation engine.
97+
* </p>
98+
*
99+
* @return the function definition or expression
100+
*/
25101
String getFunction();
26102

27103
}

platform/core/domain/src/main/java/tools/dynamia/domain/fx/MultiFunctionProcessor.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,79 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23+
/**
24+
* Interface for processing multiple functions in batch against a dataset.
25+
* <p>
26+
* This interface defines the contract for executing multiple {@link FunctionProvider} instances
27+
* against a single data source with shared arguments, returning the computed results for each function.
28+
* This is useful for bulk calculations, aggregations, or applying multiple transformations efficiently
29+
* without repeated data access.
30+
* </p>
31+
*
32+
* <p>
33+
* <b>Key benefits:</b>
34+
* <ul>
35+
* <li>Batch processing of multiple functions reduces overhead</li>
36+
* <li>Shared data context and arguments across all functions</li>
37+
* <li>Results mapped to their corresponding function providers</li>
38+
* <li>Efficient for database queries, calculations, or transformations</li>
39+
* <li>Supports parallel or optimized execution strategies</li>
40+
* </ul>
41+
* </p>
42+
*
43+
* <p>
44+
* <b>Usage example:</b>
45+
* <pre>{@code
46+
* @Component
47+
* public class SqlFunctionProcessor implements MultiFunctionProcessor<DataSource, Object> {
48+
*
49+
* @Override
50+
* public Map<FunctionProvider, Object> compute(DataSource data,
51+
* Map<String, Object> args,
52+
* List<FunctionProvider> functions) {
53+
* Map<FunctionProvider, Object> results = new HashMap<>();
54+
*
55+
* try (Connection conn = data.getConnection()) {
56+
* for (FunctionProvider function : functions) {
57+
* String sql = buildQuery(function, args);
58+
* Object result = executeQuery(conn, sql);
59+
* results.put(function, result);
60+
* }
61+
* }
62+
*
63+
* return results;
64+
* }
65+
* }
66+
*
67+
* // Usage
68+
* List<FunctionProvider> functions = Arrays.asList(totalFunction, avgFunction, maxFunction);
69+
* Map<String, Object> args = Map.of("year", 2024, "status", "active");
70+
* Map<FunctionProvider, Object> results = processor.compute(dataSource, args, functions);
71+
* }</pre>
72+
* </p>
73+
*
74+
* @param <D> the type of data source or dataset to process
75+
* @param <R> the type of result produced by each function
76+
* @author Mario A. Serrano Leones
77+
* @see FunctionProvider
78+
* @see Function
79+
*/
2380
public interface MultiFunctionProcessor<D, R> {
2481

25-
82+
/**
83+
* Computes and executes all provided functions against the given data source with the specified arguments.
84+
* <p>
85+
* This method processes all functions in the list, applying them to the data source using the shared
86+
* arguments. Each function's result is mapped to its corresponding {@link FunctionProvider} in the
87+
* returned map. Implementations may optimize execution by batching operations or executing functions
88+
* in parallel.
89+
* </p>
90+
*
91+
* @param data the data source or dataset to process (e.g., database connection, entity, collection)
92+
* @param args shared arguments/parameters available to all functions during execution
93+
* @param functions list of function providers to execute against the data
94+
* @return a map where each function provider is associated with its computed result
95+
*/
2696
Map<FunctionProvider, R> compute(D data, Map<String, Object> args, List<FunctionProvider> functions);
2797

2898

0 commit comments

Comments
 (0)