Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jocument DDSG features #102

Merged
merged 68 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
cba7d1f
Implement placeholder replacement via mapping
AntonOellerer Dec 16, 2021
dbf3c02
Implemenent future handling
AntonOellerer Dec 16, 2021
540b9bd
Refactoring
AntonOellerer Dec 21, 2021
f595a0f
Refactor to set mapping path dynamically
AntonOellerer Dec 21, 2021
7535c13
Refactor and add tests
AntonOellerer Dec 21, 2021
3e24f32
Update `CustomPlaceholderResolver` to receive bean
AntonOellerer Dec 21, 2021
b17c6fe
Prioritize directly accessible Resolved over Mapped ones in Reflectio…
alexpartsch Feb 16, 2022
dc39b98
Implement placeholder replacement via mapping
AntonOellerer Dec 16, 2021
b8f9aa4
Implemenent future handling
AntonOellerer Dec 16, 2021
5e7c6f5
Refactoring
AntonOellerer Dec 21, 2021
05adfbc
Refactor to set mapping path dynamically
AntonOellerer Dec 21, 2021
d0fae85
Refactor and add tests
AntonOellerer Dec 21, 2021
ec4657f
Update `CustomPlaceholderResolver` to receive bean
AntonOellerer Dec 21, 2021
553b3be
Add dimension parameter for inserting images
AntonOellerer Jan 28, 2022
a400392
Extend image type probing to all supported by poi
AntonOellerer Jan 31, 2022
f88ae8f
Make necessary `WordImageUtils` methods public
AntonOellerer Feb 1, 2022
7dab1dd
Make `ImageStrategy INSTANCE` volatile
AntonOellerer Feb 1, 2022
5286a8f
Upgrade to gradle 7.3.3
AntonOellerer Feb 1, 2022
122e7e9
Ign. case on fetching object field by placeholder
AntonOellerer Feb 15, 2022
5abf75b
Check if custom placeholder before loop
AntonOellerer Feb 15, 2022
bd4d72f
Improve logging
AntonOellerer Feb 15, 2022
3de8e4d
Improve logging
AntonOellerer Feb 15, 2022
3bdccec
Add timout parameter to FutureReflectionResolver
AntonOellerer Feb 16, 2022
0ae30fc
Fix naming of temporary files
AntonOellerer Feb 21, 2022
1ba6883
Ignore case when retrieving record field
AntonOellerer Feb 21, 2022
1d711af
Add MatchPlaceholder-Annotation for ReflectionResolver to support Reg…
alexpartsch Mar 1, 2022
35a538e
Bump Version to 1.4.0-alpha.16
alexpartsch Mar 1, 2022
e81bdc1
Bump Version to 1.4.0-alpha.17
alexpartsch Mar 1, 2022
cbef05e
Add concept of Parent to ReflectionResolver
alexpartsch Mar 7, 2022
47bf789
Bump Version to 1.4.0-alpha.18
alexpartsch Mar 11, 2022
af6a7b9
Bump Version to 1.4.0-alpha.20
alexpartsch Mar 11, 2022
c207f3d
Add test for case-insensitive matching
AntonOellerer Mar 15, 2022
07ab2ba
WIP Introduce Conditional Placeholders
alexpartsch Mar 15, 2022
8776fbf
Clean up conditional resolving
AntonOellerer Mar 15, 2022
2b4747b
Clean up conditional resolving
AntonOellerer Mar 15, 2022
fef1414
Enable `end-` as additional block end statement
AntonOellerer Mar 15, 2022
c40fc95
Add Abstraction Layer in PlaceholderResolver#resolve
alexpartsch Mar 17, 2022
be7c28c
Allow to Register Custom Formatters for ScalarPlaceholderData before …
alexpartsch Mar 17, 2022
bf2481a
Pass Locale down the PlaceholderData#transform Method
alexpartsch Mar 17, 2022
fc57edd
Bump Version
alexpartsch Mar 17, 2022
f2eb078
Pass GenerationOptions down to Children
alexpartsch Mar 21, 2022
0c6af0d
Pass GenerationOptions down to Children in FutureReflectionResolver
alexpartsch Mar 21, 2022
96660de
Allow to pass a Translations Function to GenerationOptions
alexpartsch Mar 22, 2022
4d4b5dc
Bump Version
alexpartsch Mar 22, 2022
1e1cedb
5009 - Implements hyperlink formula
betorcs Apr 6, 2022
b93601e
Refactor how placeholders are resolved
betorcs Apr 11, 2022
d09c202
Evaluate all formulas before saving an xssf document
AntonOellerer Feb 22, 2022
7111d67
Copy hyperlinks to new sheet
AntonOellerer Feb 22, 2022
75b697a
Bump Version
betorcs Apr 13, 2022
f112731
Bump Version
betorcs Apr 13, 2022
06df80a
Resolve optionals
AntonOellerer Apr 20, 2022
6f7a2e9
Check resolved future for optional
AntonOellerer Apr 20, 2022
3a7cbe5
Allow formatting of any object type
AntonOellerer May 3, 2022
030cb0e
Add `@Translatable` annotation
AntonOellerer May 3, 2022
de49d41
Also enable translation of enums
AntonOellerer May 3, 2022
a2f4003
Fix checkstyle issues
AntonOellerer May 9, 2022
ab9ed38
Fix gh comments
AntonOellerer May 9, 2022
6af47e2
Fix sonar problems
AntonOellerer May 9, 2022
22dd095
Add image scale test
AntonOellerer May 9, 2022
7e2bc9a
Remove unused methods
AntonOellerer May 9, 2022
6b6b23f
Move FRR logic into ReflectionResolver
AntonOellerer May 9, 2022
24b0614
Add constructor for creating parent resolver
AntonOellerer May 9, 2022
1902036
Fix mapping and parent resolving logic
AntonOellerer May 12, 2022
ed76c79
Update gradle
AntonOellerer May 12, 2022
9d930aa
Cleanup
AntonOellerer May 12, 2022
52fd714
Test collection placeholder mapping
AntonOellerer May 16, 2022
c01438a
Cleanup
AntonOellerer May 16, 2022
390040b
Add match resolving tests
AntonOellerer May 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ plugins {
}

group 'com.docutools'
version = '1.3.2'
version = '1.4.0-rc.9'

sourceCompatibility = 17
targetCompatibility = 17
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17

repositories {
mavenCentral()
Expand Down Expand Up @@ -75,6 +75,7 @@ test {
}

task automatedTests(type: Test) {
environment 'DT_JT_RR_PLACEHOLDER_MAPPINGS', 'src/test/resources/mappings.txt'
useJUnitPlatform{
includeTags "automated"
}
Expand All @@ -86,8 +87,8 @@ publishing {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/DDS-GmbH/jocument")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_USERNAME")
password = project.findProperty("gpr.token") ?: System.getenv("GITHUB_TOKEN")
username = project.findProperty("gpr.gh.user") ?: System.getenv("GITHUB_USERNAME")
password = project.findProperty("gpr.gh.token") ?: System.getenv("GITHUB_TOKEN")
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
public interface CustomPlaceholderRegistry {
void addHandler(String placeholder, Class<? extends CustomWordPlaceholderData> customWordPlaceholderDataClass);

Optional<PlaceholderData> resolve(String placeholder)
Optional<PlaceholderData> resolve(String placeholder, Object object)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException;

boolean governs(String placeholderName);
boolean governs(String placeholderName, Object object);
}
58 changes: 57 additions & 1 deletion src/main/java/com/docutools/jocument/GenerationOptions.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,68 @@
package com.docutools.jocument;

import com.docutools.jocument.formatting.PlaceholderDataFormattingOption;
import com.docutools.jocument.image.ImageStrategy;
import com.docutools.jocument.impl.ScalarPlaceholderData;
import java.time.Duration;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.function.BiFunction;

/**
* Options for generating {@link Document}s, passed to the {@link Template}s.
*
* @author partschi
* @since 2021-03-24
*/
public record GenerationOptions(ImageStrategy imageStrategy) {
public record GenerationOptions(ImageStrategy imageStrategy,
Duration maximumWaitTime,
List<PlaceholderDataFormattingOption> formattingOptions,
BiFunction<String, Locale, Optional<String>> translationFunction) {

/**
* Try to format a {@link PlaceholderData} with the given {@link Locale}.
*
* @param locale The locale to use for formatting
* @param placeholderData The data to format
* @return An {@link Optional} containing the formatted {@link PlaceholderData} if successful, {@link Optional#empty()} otherwise.
*/
public Optional<PlaceholderData> tryToFormat(Locale locale, PlaceholderData placeholderData) {
return formattingOptions.stream()
.filter(option -> option.filter().accepts(placeholderData.getRawValue()))
.findFirst()
.map(option -> option.formatter().format(locale, placeholderData.getRawValue()))
.map(ScalarPlaceholderData::new);

}

/**
* Try to format an object with the given {@link Locale}.
*
* @param locale The locale to use for formatting
* @param toFormat The data to format
* @return An {@link Optional} containing the formatted {@link String} if successful, {@link Optional#empty()} otherwise.
*/
public <T> Optional<String> tryToFormat(Locale locale, T toFormat) {
return formattingOptions.stream()
.filter(option -> option.filter().accepts(toFormat))
.findFirst()
.map(option -> option.formatter().format(locale, toFormat));

}

/**
* Translate a given term to the given locale.
*
* @param term The term to translate
* @param locale The locale to translate the term to
* @return An {@link Optional} containing the translated term if successful, {@link Optional#empty()} otherwise
*/
public Optional<String> translate(String term, Locale locale) {
if (translationFunction != null) {
return translationFunction.apply(term, locale);
}
return Optional.empty();
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
package com.docutools.jocument;

import com.docutools.jocument.formatting.LocalisedPlaceholderDataFormatter;
import com.docutools.jocument.formatting.PlaceholderDataFormatter;
import com.docutools.jocument.formatting.PlaceholderDataFormattingOption;
import com.docutools.jocument.image.DefaultImageStrategy;
import com.docutools.jocument.image.ImageStrategy;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiFunction;

/**
* Builder for {@link GenerationOptions}, use {@link this#buildDefaultOptions()} to take all default options for {@link GenerationOptions}.
Expand All @@ -17,6 +26,9 @@ public static GenerationOptions buildDefaultOptions() {
}

private ImageStrategy imageStrategy;
private final List<PlaceholderDataFormattingOption> formattingOptions = new ArrayList<>();
private BiFunction<String, Locale, Optional<String>> translationFunction = null;
private Duration waitTime = Duration.ofSeconds(30);

public GenerationOptionsBuilder() {
this.imageStrategy = DefaultImageStrategy.instance();
Expand All @@ -27,8 +39,27 @@ public GenerationOptionsBuilder withImageStrategy(ImageStrategy imageStrategy) {
return this;
}

public <T> GenerationOptionsBuilder format(Class<T> filter, PlaceholderDataFormatter<T> formatter) {
return format(filter, (l, v) -> formatter.format(v));
}

public <T> GenerationOptionsBuilder format(Class<T> filter, LocalisedPlaceholderDataFormatter<T> formatter) {
formattingOptions.add(new PlaceholderDataFormattingOption<>(obj -> obj.getClass().isAssignableFrom(filter), formatter));
return this;
}

public GenerationOptionsBuilder withTranslation(BiFunction<String, Locale, Optional<String>> translationFunction) {
this.translationFunction = translationFunction;
return this;
}

public GenerationOptionsBuilder withMaximumWaitTime(Duration waitTime) {
this.waitTime = waitTime;
return this;
}

public GenerationOptions build() {
return new GenerationOptions(imageStrategy);
return new GenerationOptions(imageStrategy, waitTime, formattingOptions, translationFunction);
}

}
31 changes: 30 additions & 1 deletion src/main/java/com/docutools/jocument/PlaceholderData.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.docutools.jocument;

import java.util.Locale;
import java.util.stream.Stream;

/**
Expand Down Expand Up @@ -49,10 +50,38 @@ default long count() {
* <p>Only used when {@link this#getType()} returns {@link com.docutools.jocument.PlaceholderType#CUSTOM}.</p>
*
* @param placeholder the placeholder
* @param locale the {@link Locale}
* @param options the {@link GenerationOptions}
*/
default void transform(Object placeholder, GenerationOptions options) {
default void transform(Object placeholder, Locale locale, GenerationOptions options) {
throw new UnsupportedOperationException();
}

/**
* Tries to return the raw value behind the {@link PlaceholderData}. May not be implemented in all sepcifications.
*
* @return the raw value
*/
default Object getRawValue() {
throw new UnsupportedOperationException();
}

/**
* Evaluates if this {@link PlaceholderData} is a truthy value. Non-truthy values are defined as:
*
* <ul>
* <li>Empty string</li>
* <li>Empty collection or array</li>
* <li>{@code null}</li>
* <li>0</li>
* <li>{@code false}</li>
* <li>Empty {@link java.util.Optional}</li>
* </ul>
*
* @return {@code true} if truthy
*/
default boolean isTruthy() {
return count() > 0;
}

}
9 changes: 9 additions & 0 deletions src/main/java/com/docutools/jocument/PlaceholderMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.docutools.jocument;

import java.util.Optional;

public interface PlaceholderMapper {
Optional<String> map(String placeholder);

String tryToMap(String placeholder);
}
15 changes: 14 additions & 1 deletion src/main/java/com/docutools/jocument/PlaceholderResolver.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.docutools.jocument;

import com.docutools.jocument.impl.ScalarPlaceholderData;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -41,6 +42,18 @@ public Optional<PlaceholderData> resolve(String placeholderName) {
* @param locale the localisation settings
* @return if the name could've been resolved the localised {@link com.docutools.jocument.PlaceholderData}
*/
public abstract Optional<PlaceholderData> resolve(String placeholderName, Locale locale);
public Optional<PlaceholderData> resolve(String placeholderName, Locale locale) {
return doResolve(placeholderName, locale)
.map(placeholderData -> format(locale, placeholderData));
}

private PlaceholderData format(Locale locale, PlaceholderData original) {
if (original instanceof ScalarPlaceholderData<?>) {
return options.tryToFormat(locale, original).orElse(original);
}
return original;
}

protected abstract Optional<PlaceholderData> doResolve(String placeholderName, Locale locale);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.docutools.jocument.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;

/**
* Allows to define a regular expression pattern for a method to be resolved in a {@link com.docutools.jocument.impl.ReflectionResolver} if the
* placeholder name passed to {@link com.docutools.jocument.impl.ReflectionResolver#resolve(String, Locale)} matches against the {@link
* this#pattern()}.
*
* <p>{@link MatchPlaceholder}-annotated methods precede any other properties.
*
* <p>Can be applied to a public method taking a {@link String} and an optional {@link java.util.Locale} as second parameter, returning an {@link
* java.util.Optional} of {@link String}.
*
* @author amp
* @since 2022-03-01
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MatchPlaceholder {
/**
* A RegEx pattern.
*
* @return {@link String}
*/
String pattern();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.docutools.jocument.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Translatable {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.docutools.jocument.formatting;

import java.util.Locale;

public interface LocalisedPlaceholderDataFormatter<T> {

String format(Locale locale, T value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.docutools.jocument.formatting;

public interface PlaceholderDataFormatter<T> {

String format(T value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.docutools.jocument.formatting;

public interface PlaceholderDataFormatterFilter {

boolean accepts(Object value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.docutools.jocument.formatting;

import com.docutools.jocument.PlaceholderData;

/**
* An option for formatting {@link PlaceholderData} by a specific {@link PlaceholderDataFormatter}, given the {@link PlaceholderDataFormatterFilter}
* accepts it.
*
* @param <T> the {@link PlaceholderData#getRawValue()} type.
*/
public record PlaceholderDataFormattingOption<T>(PlaceholderDataFormatterFilter filter,
LocalisedPlaceholderDataFormatter<T> formatter) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public Path saveAsJpeg() throws IOException {
throw new ImageReferenceClosedException("Image was already closed.");
}

var filePath = Files.createTempFile("jocument", "jpg");
var filePath = Files.createTempFile("jocument-", ".jpg");
log.trace("Saving image {} to '{}'...", id, filePath);

ImageIO.write(image, "JPEG", filePath.toFile());
Expand Down
Loading