OfficeStamperConfigurations.java
package pro.verron.officestamper.preset;
import pro.verron.officestamper.api.ObjectResolver;
import pro.verron.officestamper.api.OfficeStamperConfiguration;
import pro.verron.officestamper.api.OfficeStamperException;
import pro.verron.officestamper.core.DocxStamperConfiguration;
import pro.verron.officestamper.preset.CommentProcessorFactory.*;
import pro.verron.officestamper.preset.processors.displayif.DisplayIfProcessor;
import pro.verron.officestamper.preset.processors.repeat.RepeatDocPartProcessor;
import pro.verron.officestamper.preset.processors.repeat.RepeatParagraphProcessor;
import pro.verron.officestamper.preset.processors.repeat.RepeatProcessor;
import pro.verron.officestamper.preset.processors.repeatrow.RepeatRowProcessor;
import pro.verron.officestamper.preset.processors.replacewith.ReplaceWithProcessor;
import pro.verron.officestamper.preset.processors.table.TableResolver;
import java.time.temporal.TemporalAccessor;
import java.util.List;
import static java.time.format.DateTimeFormatter.*;
import static java.time.format.FormatStyle.valueOf;
import static java.util.Locale.forLanguageTag;
/// Utility class providing factory methods for various pre-configured instances of [OfficeStamperConfiguration].
///
/// These configurations range from minimal to fully-featured, catering to different use cases for processing Office
/// documents.
public class OfficeStamperConfigurations {
private OfficeStamperConfigurations() {
throw new OfficeStamperException("Utility class should not be instantiated");
}
/// Creates a full [OfficeStamperConfiguration] with standard configurations, supplemented with additional pre- and
/// post-processors for enhanced document handling.
///
/// This configuration includes preprocessors to:
/// - Remove language proof markings.
/// - Remove language information.
/// - Merge similar text runs.
///
/// It also includes postprocessors to:
/// - Remove orphaned footnotes.
/// - Remove orphaned endnotes.
///
/// @return a fully configured [OfficeStamperConfiguration] instance with the additional processors applied.
public static OfficeStamperConfiguration full() {
var configuration = standard();
configuration.addPreprocessor(Preprocessors.removeLanguageProof());
configuration.addPreprocessor(Preprocessors.removeLanguageInfo());
configuration.addPreprocessor(Preprocessors.mergeSimilarRuns());
configuration.addPostprocessor(Postprocessors.removeOrphanedFootnotes());
configuration.addPostprocessor(Postprocessors.removeOrphanedEndnotes());
return configuration;
}
/// Creates a standard [OfficeStamperConfiguration] instance with predefined settings.
///
/// The configuration is extended with custom comment processing, resolvers, and additional preprocessors.
///
/// It sets up a fallback resolver with the default value of a newline character ("`\n`") to handle placeholder
/// resolution.
///
/// @return a standard [OfficeStamperConfiguration] instance with pre-configured resolvers and processors
public static OfficeStamperConfiguration standard() {
var fallback = Resolvers.fallback("\n");
return standard(fallback);
}
/// Creates a standard [OfficeStamperConfiguration] instance with a set of predefined comment processors, resolvers,
/// and preprocessors.
///
/// The configuration is extended with custom functions for date and time formatting, and permits the provision of a
/// custom fallback resolver.
///
/// @param fallback an [ObjectResolver] to serve as the additional fallback resolver for this
/// configuration.
///
/// @return a configured [OfficeStamperConfiguration] object implementing standard processing and formatting
/// behaviors
public static OfficeStamperConfiguration standard(ObjectResolver fallback) {
var configuration = minimal();
configuration.addCommentProcessor(IRepeatRowProcessor.class, RepeatRowProcessor::new);
configuration.addCommentProcessor(IParagraphRepeatProcessor.class, RepeatParagraphProcessor::new);
configuration.addCommentProcessor(IRepeatDocPartProcessor.class, RepeatDocPartProcessor::new);
configuration.addCommentProcessor(IRepeatProcessor.class, RepeatProcessor::new);
configuration.addCommentProcessor(ITableResolver.class, TableResolver::new);
configuration.addCommentProcessor(IDisplayIfProcessor.class, DisplayIfProcessor::new);
configuration.addCommentProcessor(IReplaceWithProcessor.class, ReplaceWithProcessor::new);
configuration.setResolvers(List.of(Resolvers.image(),
Resolvers.legacyDate(),
Resolvers.isoDate(),
Resolvers.isoTime(),
Resolvers.isoDateTime(),
Resolvers.nullToEmpty(),
fallback));
configuration.addPreprocessor(Preprocessors.removeMalformedComments());
var fdate = "fdate";
var ftime = "ftime";
var fdatetime = "fdatetime";
var fpattern = "fpattern";
var flocaldate = "flocaldate";
var flocaltime = "flocaltime";
var flocaldatetime = "flocaldatetime";
var finstant = "finstant";
var fordinaldate = "fordinaldate";
var f1123datetime = "f1123datetime";
var fbasicdate = "fbasicdate";
var fweekdate = "fweekdate";
var foffsetdatetime = "foffsetdatetime";
var fzoneddatetime = "fzoneddatetime";
var foffsetdate = "foffsetdate";
var foffsettime = "foffsettime";
configuration.addCustomFunction(fdate, TemporalAccessor.class)
.withImplementation(ISO_DATE::format)
.addCustomFunction(ftime, TemporalAccessor.class)
.withImplementation(ISO_TIME::format)
.addCustomFunction(fdatetime, TemporalAccessor.class)
.withImplementation(ISO_DATE_TIME::format)
.addCustomFunction(finstant, TemporalAccessor.class)
.withImplementation(ISO_INSTANT::format)
.addCustomFunction(fordinaldate, TemporalAccessor.class)
.withImplementation(ISO_ORDINAL_DATE::format)
.addCustomFunction(f1123datetime, TemporalAccessor.class)
.withImplementation(RFC_1123_DATE_TIME::format)
.addCustomFunction(fbasicdate, TemporalAccessor.class)
.withImplementation(BASIC_ISO_DATE::format)
.addCustomFunction(fweekdate, TemporalAccessor.class)
.withImplementation(ISO_WEEK_DATE::format)
.addCustomFunction(flocaldatetime, TemporalAccessor.class)
.withImplementation(ISO_LOCAL_DATE_TIME::format)
.addCustomFunction(flocaldatetime, TemporalAccessor.class, String.class)
.withImplementation(OfficeStamperConfigurations::flocaldatetime)
.addCustomFunction(flocaldatetime, TemporalAccessor.class, String.class, String.class)
.withImplementation(OfficeStamperConfigurations::flocaldatetime)
.addCustomFunction(foffsetdatetime, TemporalAccessor.class)
.withImplementation(ISO_OFFSET_DATE_TIME::format)
.addCustomFunction(fzoneddatetime, TemporalAccessor.class)
.withImplementation(ISO_ZONED_DATE_TIME::format)
.addCustomFunction(foffsetdate, TemporalAccessor.class)
.withImplementation(ISO_OFFSET_DATE::format)
.addCustomFunction(foffsettime, TemporalAccessor.class)
.withImplementation(ISO_OFFSET_TIME::format)
.addCustomFunction(flocaldate, TemporalAccessor.class)
.withImplementation(ISO_LOCAL_DATE::format)
.addCustomFunction(flocaldate, TemporalAccessor.class, String.class)
.withImplementation(OfficeStamperConfigurations::flocaldate)
.addCustomFunction(flocaltime, TemporalAccessor.class)
.withImplementation(ISO_LOCAL_TIME::format)
.addCustomFunction(flocaltime, TemporalAccessor.class, String.class)
.withImplementation(OfficeStamperConfigurations::flocaltime)
.addCustomFunction(fpattern, TemporalAccessor.class, String.class)
.withImplementation(OfficeStamperConfigurations::fpattern)
.addCustomFunction(fpattern, TemporalAccessor.class, String.class, String.class)
.withImplementation(OfficeStamperConfigurations::fpattern);
return configuration;
}
/// Creates a minimal [OfficeStamperConfiguration] instance with essential settings to provide basic placeholder
/// processing and fallback resolvers.
///
/// This configuration includes:
/// - A fallback resolver with a default value of a newline character ("`\n`").
/// - A placeholder preprocessor that prepares placeholders matching a specific pattern.
///
/// @return a minimally configured [OfficeStamperConfiguration] instance
public static OfficeStamperConfiguration minimal() {
var configuration = raw();
configuration.addResolver(Resolvers.fallback("\n"));
configuration.addPreprocessor(Preprocessors.preparePlaceholders("(\\$\\{([^{]+?)})", "placeholder"));
configuration.addPreprocessor(Preprocessors.preparePlaceholders("(\\#\\{([^{]+?)})", "inlineProcessor"));
configuration.addPreprocessor(Preprocessors.prepareCommentProcessor());
configuration.addPostprocessor(Postprocessors.removeTags("officestamper"));
return configuration;
}
private static Object flocaldatetime(TemporalAccessor date, String style) {
return ofLocalizedDateTime(valueOf(style)).format(date);
}
private static Object flocaldatetime(TemporalAccessor date, String dateStyle, String timeStyle) {
return ofLocalizedDateTime(valueOf(dateStyle), valueOf(timeStyle)).format(date);
}
private static Object flocaldate(TemporalAccessor date, String style) {
return ofLocalizedDate(valueOf(style)).format(date);
}
private static Object flocaltime(TemporalAccessor date, String style) {
return ofLocalizedTime(valueOf(style)).format(date);
}
private static Object fpattern(TemporalAccessor date, String pattern) {
return ofPattern(pattern).format(date);
}
private static Object fpattern(TemporalAccessor date, String pattern, String locale) {
return ofPattern(pattern, forLanguageTag(locale)).format(date);
}
/// Creates a [OfficeStamperConfiguration] instance without any configuration or resolvers, processors,
/// preprocessors or postprocessors applied.
///
/// @return a basic [OfficeStamperConfiguration] instance with no extra configurations
public static OfficeStamperConfiguration raw() {
var defaultFactory = EvaluationContextFactories.defaultFactory();
var defaultExceptionResolver = ExceptionResolvers.throwing();
return new DocxStamperConfiguration(defaultFactory, defaultExceptionResolver);
}
}