All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javers.core.JaversBuilder Maven / Gradle / Ivy

package org.javers.core;

import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import org.javers.common.collections.Lists;
import org.javers.common.date.DateProvider;
import org.javers.common.date.DefaultDateProvider;
import org.javers.common.validation.Validate;
import org.javers.core.JaversCoreProperties.PrettyPrintDateFormats;
import org.javers.core.commit.Commit;
import org.javers.core.commit.CommitFactoryModule;
import org.javers.core.commit.CommitId;
import org.javers.core.diff.Diff;
import org.javers.core.diff.DiffFactoryModule;
import org.javers.core.diff.ListCompareAlgorithm;
import org.javers.core.diff.appenders.DiffAppendersModule;
import org.javers.core.diff.changetype.*;
import org.javers.core.diff.changetype.container.ListChange;
import org.javers.core.diff.changetype.container.ValueAdded;
import org.javers.core.diff.custom.*;
import org.javers.core.graph.GraphFactoryModule;
import org.javers.core.graph.ObjectAccessHook;
import org.javers.core.graph.TailoredJaversMemberFactoryModule;
import org.javers.core.json.JsonAdvancedTypeAdapter;
import org.javers.core.json.JsonConverter;
import org.javers.core.json.JsonConverterBuilder;
import org.javers.core.json.JsonTypeAdapter;
import org.javers.core.json.typeadapter.change.ChangeTypeAdaptersModule;
import org.javers.core.json.typeadapter.commit.CommitTypeAdaptersModule;
import org.javers.core.json.typeadapter.commit.DiffTypeDeserializer;
import org.javers.core.metamodel.annotation.*;
import org.javers.core.metamodel.clazz.*;
import org.javers.core.metamodel.scanner.ScannerModule;
import org.javers.core.metamodel.type.*;
import org.javers.core.pico.AddOnsModule;
import org.javers.core.snapshot.SnapshotModule;
import org.javers.groovysupport.GroovyAddOns;
import org.javers.guava.GuavaAddOns;
import org.javers.jodasupport.JodaAddOns;
import org.javers.mongosupport.MongoLong64JsonDeserializer;
import org.javers.mongosupport.RequiredMongoSupportPredicate;
import org.javers.repository.api.ConfigurationAware;
import org.javers.repository.api.JaversExtendedRepository;
import org.javers.repository.api.JaversRepository;
import org.javers.repository.inmemory.InMemoryRepository;
import org.javers.repository.jql.JqlModule;
import org.javers.repository.jql.JqlQuery;
import org.javers.shadow.ShadowModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

import static org.javers.common.reflection.ReflectionUtil.findClasses;
import static org.javers.common.reflection.ReflectionUtil.isClassPresent;
import static org.javers.common.validation.Validate.argumentIsNotNull;
import static org.javers.common.validation.Validate.argumentsAreNotNull;

/**
 * Creates a JaVers instance based on your domain model metadata and custom configuration.
 * 

* * For example, to build a JaVers instance configured with reasonable defaults: *
 * Javers javers = JaversBuilder.javers().build();
 * 
* * To build a JaVers instance with an Entity type: *
 * Javers javers = JaversBuilder.javers()
 *                              .registerEntity(MyEntity.class)
 *                              .build();
 * 
* * @see http://javers.org/documentation/domain-configuration * @author bartosz walacik */ public class JaversBuilder extends AbstractContainerBuilder { public static final Logger logger = LoggerFactory.getLogger(JaversBuilder.class); private final Map clientsClassDefinitions = new LinkedHashMap<>(); private final Map> mappedToStringFunction = new ConcurrentHashMap<>(); private final Set classesToScan = new HashSet<>(); private final Set conditionalTypesPlugins; private CoreConfigurationBuilder coreConfigurationBuilder = CoreConfigurationBuilder.coreConfiguration(); private JaversRepository repository; private DateProvider dateProvider; private long bootStart = System.currentTimeMillis(); private IgnoredClassesStrategy ignoredClassesStrategy; public static JaversBuilder javers() { return new JaversBuilder(); } /** * use static factory method {@link JaversBuilder#javers()} */ protected JaversBuilder() { logger.debug("starting up JaVers ..."); //conditional plugins conditionalTypesPlugins = new HashSet<>(); if (isClassPresent("groovy.lang.MetaClass")) { conditionalTypesPlugins.add(new GroovyAddOns()); } if (isClassPresent("org.joda.time.LocalDate")){ conditionalTypesPlugins.add(new JodaAddOns()); } if (isClassPresent("com.google.common.collect.Multimap")) { conditionalTypesPlugins.add(new GuavaAddOns()); } // bootstrap pico container & core module bootContainer(); addModule(new CoreJaversModule(getContainer())); } public Javers build() { Javers javers = assembleJaversInstance(); repository.ensureSchema(); long boot = System.currentTimeMillis() - bootStart; logger.info("JaVers instance started in {} ms", boot); return javers; } protected Javers assembleJaversInstance(){ CoreConfiguration coreConfiguration = configurationBuilder().build(); addComponent(coreConfiguration); // boot main modules addModule(new DiffFactoryModule()); addModule(new CommitFactoryModule(getContainer())); addModule(new SnapshotModule(getContainer())); addModule(new GraphFactoryModule(getContainer())); addModule(new DiffAppendersModule(coreConfiguration, getContainer())); addModule(new TailoredJaversMemberFactoryModule(coreConfiguration, getContainer())); addModule(new ScannerModule(coreConfiguration, getContainer())); addModule(new ShadowModule(getContainer())); addModule(new JqlModule(getContainer())); // boot add-ons modules Set additionalTypes = bootAddOns(); // boot TypeMapper module addComponent(new DynamicMappingStrategy(ignoredClassesStrategy)); addModule(new TypeMapperModule(getContainer())); // boot JSON beans & domain aware typeAdapters bootJsonConverter(); bootDateTimeProvider(); // clases to scan & additionalTypes for (Class c : classesToScan){ typeMapper().getJaversType(c); } typeMapper().addPluginTypes(additionalTypes); mapRegisteredClasses(); bootRepository(); return getContainerComponent(JaversCore.class); } /** * @see http://javers.org/documentation/repository-configuration */ public JaversBuilder registerJaversRepository(JaversRepository repository) { argumentsAreNotNull(repository); this.repository = repository; return this; } /** * Registers an {@link EntityType}.
* Use @Id annotation to mark exactly one Id-property. *

* * Optionally, use @Transient or @{@link DiffIgnore} annotations to mark ignored properties. *

* * For example, Entities are: Person, Document * * @see http://javers.org/documentation/domain-configuration/#entity * @see #registerEntity(EntityDefinition) */ public JaversBuilder registerEntity(Class entityClass) { argumentIsNotNull(entityClass); return registerEntity( new EntityDefinition(entityClass)); } /** * Registers a {@link ValueObjectType}.
* Optionally, use @Transient or @{@link DiffIgnore} annotations to mark ignored properties. *

* * For example, ValueObjects are: Address, Point * * @see http://javers.org/documentation/domain-configuration/#value-object * @see #registerValueObject(ValueObjectDefinition) */ public JaversBuilder registerValueObject(Class valueObjectClass) { argumentIsNotNull(valueObjectClass); registerType(new ValueObjectDefinition(valueObjectClass)); return this; } /** * Registers an {@link EntityType}.
* Use this method if you are not willing to use {@link Entity} annotation. *

* * Recommended way to create {@link EntityDefinition} is {@link EntityDefinitionBuilder}, * for example: *
     * javersBuilder.registerEntity(
     *     EntityDefinitionBuilder.entityDefinition(Person.class)
     *     .withIdPropertyName("id")
     *     .withTypeName("Person")
     *     .withIgnoredProperties("notImportantProperty","transientProperty")
     *     .build());
     * 
* * For simple cases, you can use {@link EntityDefinition} constructors, * for example: *
     * javersBuilder.registerEntity( new EntityDefinition(Person.class, "login") );
     * 
* * @see http://javers.org/documentation/domain-configuration/#entity * @see EntityDefinitionBuilder#entityDefinition(Class) */ public JaversBuilder registerEntity(EntityDefinition entityDefinition){ argumentIsNotNull(entityDefinition); return registerType(entityDefinition); } /** * Generic version of {@link #registerEntity(EntityDefinition)} and * {@link #registerValueObject(ValueObjectDefinition)} */ public JaversBuilder registerType(ClientsClassDefinition clientsClassDefinition) { argumentIsNotNull(clientsClassDefinition); clientsClassDefinitions.put(clientsClassDefinition.getBaseJavaClass(), clientsClassDefinition); return this; } public JaversBuilder registerTypes(Collection clientsClassDefinitions) { argumentIsNotNull(clientsClassDefinitions); clientsClassDefinitions.forEach(it -> registerType(it)); return this; } /** * Registers a {@link ValueObjectType}.
* Use this method if you are not willing to use {@link ValueObject} annotations. *

* * Recommended way to create {@link ValueObjectDefinition} is {@link ValueObjectDefinitionBuilder}. * For example: *
     * javersBuilder.registerValueObject(ValueObjectDefinitionBuilder.valueObjectDefinition(Address.class)
     *     .withIgnoredProperties(ignoredProperties)
     *     .withTypeName(typeName)
     *     .build();
     * 
* * For simple cases, you can use {@link ValueObjectDefinition} constructors, * for example: *
     * javersBuilder.registerValueObject( new ValueObjectDefinition(Address.class, "ignored") );
     * 
* * @see http://javers.org/documentation/domain-configuration/#value-object * @see ValueObjectDefinitionBuilder#valueObjectDefinition(Class) */ public JaversBuilder registerValueObject(ValueObjectDefinition valueObjectDefinition) { argumentIsNotNull(valueObjectDefinition); registerType(valueObjectDefinition); return this; } /** * Comma separated list of packages scanned by Javers in search of * your classes with the {@link TypeName} annotation. *

* * It's important to declare here all of your packages containing classes with {@literal @}TypeName,
* because Javers needs live class definitions to properly deserialize Snapshots from {@link JaversRepository}. *

* * For example, consider this class: * *
     * {@literal @}Entity
     * {@literal @}TypeName("Person")
     *  class Person {
     *     {@literal @}Id
     *      private int id;
     *      private String name;
     *  }
     * 
* * In the scenario when Javers reads a Snapshot of type named 'Person' * before having a chance to map the Person class definition, * the 'Person' type will be mapped to generic {@link UnknownType}. *

* * Since 5.8.4, Javers logs WARNING when UnknownType is created * because Snapshots with UnknownType can't be properly deserialized from {@link JaversRepository}. * * @param packagesToScan e.g. "my.company.domain.person, my.company.domain.finance" * @since 2.3 */ public JaversBuilder withPackagesToScan(String packagesToScan) { if (packagesToScan == null || packagesToScan.trim().isEmpty()) { return this; } long start = System.currentTimeMillis(); logger.info("scanning package(s): {}", packagesToScan); List> scan = findClasses(TypeName.class, packagesToScan.replaceAll(" ","").split(",")); for (Class c : scan) { scanTypeName(c); } long delta = System.currentTimeMillis() - start; logger.info(" found {} ManagedClass(es) with @TypeName in {} ms", scan.size(), delta); return this; } /** * Register your class with @{@link TypeName} annotation * in order to use it in all kinds of JQL queries. *

* * You can also use {@link #withPackagesToScan(String)} * to scan all your classes. *

* * Technically, this method is the convenient alias for {@link Javers#getTypeMapping(Type)} * * @since 1.4 */ public JaversBuilder scanTypeName(Class userType){ classesToScan.add(userType); return this; } /** * Registers a simple value type (see {@link ValueType}). *

* * For example, values are: BigDecimal, LocalDateTime. *

* * Use this method if can't use the {@link Value} annotation. *

* * By default, Values are compared using {@link Object#equals(Object)}. * You can provide external equals() function * by registering a {@link CustomValueComparator}. * See {@link #registerValue(Class, CustomValueComparator)}. * * @see http://javers.org/documentation/domain-configuration/#ValueType */ public JaversBuilder registerValue(Class valueClass) { argumentIsNotNull(valueClass); registerType(new ValueDefinition(valueClass)); return this; } /** * Registers a {@link ValueType} with a custom comparator to be used instead of * {@link Object#equals(Object)}. *

* * For example, by default, BigDecimals are Values * compared using {@link java.math.BigDecimal#equals(Object)}, * sadly it isn't the correct mathematical equality: * *
     *     new BigDecimal("1.000").equals(new BigDecimal("1.00")) == false
     * 
* * If you want to compare them in the right way — ignoring trailing zeros — * register this comparator: * *
     * JaversBuilder.javers()
     *     .registerValue(BigDecimal.class, new BigDecimalComparatorWithFixedEquals())
     *     .build();
     * 
* * @param Value Type * @see http://javers.org/documentation/domain-configuration/#ValueType * @see https://javers.org/documentation/diff-configuration/#custom-comparators * @see BigDecimalComparatorWithFixedEquals * @see CustomBigDecimalComparator * @since 3.3 */ public JaversBuilder registerValue(Class valueClass, CustomValueComparator customValueComparator) { argumentsAreNotNull(valueClass, customValueComparator); registerType(new ValueDefinition(valueClass, customValueComparator)); return this; } /** * Lambda-style variant of {@link #registerValue(Class, CustomValueComparator)}. *

* * For example, you can register the comparator for BigDecimals with fixed equals: * *
     * Javers javers = JaversBuilder.javers()
     *     .registerValue(BigDecimal.class, (a, b) -> a.compareTo(b) == 0,
     *                                           a -> a.stripTrailingZeros().toString())
     *     .build();
     * 
* * @param Value Type * @see #registerValue(Class, CustomValueComparator) * @since 5.8 */ public JaversBuilder registerValue(Class valueClass, BiFunction equalsFunction, Function toStringFunction) { Validate.argumentsAreNotNull(valueClass, equalsFunction, toStringFunction); return registerValue(valueClass, new CustomValueComparator() { @Override public boolean equals(T a, T b) { return equalsFunction.apply(a,b); } @Override public String toString(@Nonnull T value) { return toStringFunction.apply(value); } }); } /** * Deprecated, use {@link #registerValue(Class, CustomValueComparator)}. * *

* * Since this comparator is not aligned with {@link Object#hashCode()}, * it calculates incorrect results when a given Value is used in hashing context * (when comparing Sets with Values or Maps with Values as keys). * * @see CustomValueComparator */ @Deprecated public JaversBuilder registerValue(Class valueClass, BiFunction equalsFunction) { Validate.argumentsAreNotNull(valueClass, equalsFunction); return registerValue(valueClass, new CustomValueComparator() { @Override public boolean equals(T a, T b) { return equalsFunction.apply(a,b); } @Override public String toString(@Nonnull T value) { return value.toString(); } }); } /** * Deprecated, use {@link #registerValue(Class, CustomValueComparator)}. * * @see CustomValueComparator * @since 3.7.6 */ @Deprecated public JaversBuilder registerValueWithCustomToString(Class valueClass, Function toStringFunction) { Validate.argumentsAreNotNull(valueClass, toStringFunction); return registerValue(valueClass, (a,b) -> Objects.equals(a,b), toStringFunction); } /** * Marks given class as ignored by JaVers. *

* * Use this method as an alternative to the {@link DiffIgnore} annotation. * * @see DiffIgnore */ public JaversBuilder registerIgnoredClass(Class ignoredClass) { argumentIsNotNull(ignoredClass); registerType(new IgnoredTypeDefinition(ignoredClass)); return this; } /** * A dynamic version of {@link JaversBuilder#registerIgnoredClass(Class)}. *
* Registers a custom strategy for marking certain classes as ignored. *

* * For example, you can ignore classes by package naming convention: * *
     * Javers javers = JaversBuilder.javers()
     *         .registerIgnoredClassesStrategy(c -> c.getName().startsWith("com.ignore.me"))
     *         .build();
     * 
* * Use this method as the alternative to the {@link DiffIgnore} annotation * or multiple calls of {@link JaversBuilder#registerIgnoredClass(Class)}. */ public JaversBuilder registerIgnoredClassesStrategy(IgnoredClassesStrategy ignoredClassesStrategy) { argumentIsNotNull(ignoredClassesStrategy); this.ignoredClassesStrategy = ignoredClassesStrategy; return this; } /** * Registers a {@link ValueType} and its custom JSON TypeAdapter. *

* * Useful for ValueTypes when Gson's default representation isn't good enough. * * @see http://javers.org/documentation/repository-configuration/#json-type-adapters * @see JsonTypeAdapter */ public JaversBuilder registerValueTypeAdapter(JsonTypeAdapter typeAdapter) { for (Class c : (List)typeAdapter.getValueTypes()){ registerValue(c); } jsonConverterBuilder().registerJsonTypeAdapter(typeAdapter); return this; } /** * Registers an advanced variant of custom JSON TypeAdapter. * @see JsonAdvancedTypeAdapter */ public JaversBuilder registerJsonAdvancedTypeAdapter(JsonAdvancedTypeAdapter adapter) { jsonConverterBuilder().registerJsonAdvancedTypeAdapter(adapter); return this; } /** * Registers {@link ValueType} and its custom native * Gson adapter. *

* * Useful when you already have Gson {@link TypeAdapter}s implemented. * * @see TypeAdapter */ public JaversBuilder registerValueGsonTypeAdapter(Class valueType, TypeAdapter nativeAdapter) { registerValue(valueType); jsonConverterBuilder().registerNativeTypeAdapter(valueType, nativeAdapter); return this; } /** * Switch on when you need a type safe serialization for * heterogeneous collections like List, List<Object>. *

* * Heterogeneous collections are collections which contains items of different types * (or types unknown at compile time). *

* * This approach is generally discouraged, prefer statically typed collections * with exactly one type of items like List<String>. * * @see org.javers.core.json.JsonConverterBuilder#typeSafeValues(boolean) * @param typeSafeValues default false */ public JaversBuilder withTypeSafeValues(boolean typeSafeValues) { jsonConverterBuilder().typeSafeValues(typeSafeValues); return this; } /** * choose between JSON pretty or concise printing style, i.e. : * *

  • pretty: *
         * {
         *     "value": 5
         * }
         * 
    *
  • concise: *
         * {"value":5}
         * 
    *
* * @see GsonBuilder#setPrettyPrinting() * @param prettyPrint default true */ public JaversBuilder withPrettyPrint(boolean prettyPrint) { this.coreConfigurationBuilder.withPrettyPrint(prettyPrint); return this; } public JaversBuilder registerEntities(Class... entityClasses) { for(Class clazz : entityClasses) { registerEntity(clazz); } return this; } public JaversBuilder registerValueObjects(Class... valueObjectClasses) { for(Class clazz : valueObjectClasses) { registerValueObject(clazz); } return this; } /** * Default style is {@link MappingStyle#FIELD}. * * @see http://javers.org/documentation/domain-configuration/#property-mapping-style */ public JaversBuilder withMappingStyle(MappingStyle mappingStyle) { argumentIsNotNull(mappingStyle); configurationBuilder().withMappingStyle(mappingStyle); return this; } /** *
    *
  • {@link CommitIdGenerator#SYNCHRONIZED_SEQUENCE} — for non-distributed applications *
  • {@link CommitIdGenerator#RANDOM} — for distributed applications *
* SYNCHRONIZED_SEQUENCE is used by default. */ public JaversBuilder withCommitIdGenerator(CommitIdGenerator commitIdGenerator) { configurationBuilder().withCommitIdGenerator(commitIdGenerator); return this; } JaversBuilder withCustomCommitIdGenerator(Supplier commitIdGenerator) { configurationBuilder().withCustomCommitIdGenerator(commitIdGenerator); return this; } /** * The Initial Changes switch, enabled by default since Javers 6.0. *

* * When the switch is enabled, {@link Javers#compare(Object oldVersion, Object currentVersion)} * and {@link Javers#findChanges(JqlQuery)} * generate additional set of Initial Changes for each * property of a NewObject to capture its state. *
* Internally, Javers generates Initial Changes by comparing a virtual, totally empty object * with a real NewObject. * *

* For Primitives and Values * an Initial Change is modeled as {@link InitialValueChange} (subtype of {@link ValueChange}) * with null on left, and a property value on right. *
* For Collections, there are no specific subtypes to mark Initial Changes. * So, for example, an Initial Change for a List is a regular {@link ListChange} * with all elements from this list reflected as {@link ValueAdded}. *

* * In Javers Spring Boot starter you can disabled initial Value Changes in `application.yml`: * *
     * javers:
     *   initialChanges: false
     * 
* @see NewObject */ public JaversBuilder withInitialChanges(boolean initialChanges){ configurationBuilder().withInitialChanges(initialChanges); return this; } /** * Use {@link #withInitialChanges(boolean)} */ @Deprecated public JaversBuilder withNewObjectsSnapshot(boolean newObjectsSnapshot){ return this.withInitialChanges(newObjectsSnapshot); } /** * Enabled by default since Javers 6.0. *

* * When the switch is enabled, {@link Javers#compare(Object oldVersion, Object currentVersion)} * and {@link Javers#findChanges(JqlQuery)} * generate additional set of Terminal Changes for each * property of a Removed Object to capture its state. *
* Internally, Javers generates Terminal Changes by comparing * a real Removed Object with a virtual, totally empty object. *

* * In Javers Spring Boot starter you can disabled terminal Value Changes in `application.yml`: * *
     * javers:
     *   terminalChanges: false
     * 
* * @since 6.0 * @see ObjectRemoved */ public JaversBuilder withTerminalChanges(boolean terminalChanges){ configurationBuilder().withTerminalChanges(terminalChanges); return this; } public JaversBuilder withObjectAccessHook(ObjectAccessHook objectAccessHook) { removeComponent(ObjectAccessHook.class); bindComponent(ObjectAccessHook.class, objectAccessHook); return this; } /** * Registers a {@link CustomPropertyComparator} for a given class and maps this class * to {@link CustomType}. *

* * * Custom Types are not easy to manage, use it as a last resort,
* only for corner cases like comparing custom Collection types.
*

* * In most cases, it's better to customize the Javers' diff algorithm using * much more simpler {@link CustomValueComparator}, * see {@link #registerValue(Class, CustomValueComparator)}. * * @param Custom Type * @see https://javers.org/documentation/diff-configuration/#custom-comparators */ public JaversBuilder registerCustomType(Class customType, CustomPropertyComparator comparator){ registerType(new CustomDefinition(customType, comparator)); bindComponent(comparator, new CustomToNativeAppenderAdapter(comparator, customType)); return this; } /** * @deprecated Renamed to {@link #registerCustomType(Class, CustomPropertyComparator)} */ @Deprecated public JaversBuilder registerCustomComparator(CustomPropertyComparator comparator, Class customType){ return registerCustomType(customType, comparator); } /** * Choose between two algorithms for comparing list: ListCompareAlgorithm.SIMPLE * or ListCompareAlgorithm.LEVENSHTEIN_DISTANCE. *

* Generally, we recommend using LEVENSHTEIN_DISTANCE, because it's smarter. * However, it can be slow for long lists, so SIMPLE is enabled by default. *

* * Refer to http://javers.org/documentation/diff-configuration/#list-algorithms * for description of both algorithms * * @param algorithm ListCompareAlgorithm.SIMPLE is used by default */ public JaversBuilder withListCompareAlgorithm(ListCompareAlgorithm algorithm) { argumentIsNotNull(algorithm); configurationBuilder().withListCompareAlgorithm(algorithm); return this; } /** * DateProvider providers current timestamp for {@link Commit#getCommitDate()}. *
* By default, now() is used. *
* Overriding default dateProvider probably makes sense only in test environment. */ public JaversBuilder withDateTimeProvider(DateProvider dateProvider) { argumentIsNotNull(dateProvider); this.dateProvider = dateProvider; return this; } public JaversBuilder withPrettyPrintDateFormats(PrettyPrintDateFormats prettyPrintDateFormats) { configurationBuilder().withPrettyPrintDateFormats(prettyPrintDateFormats); return this; } public JaversBuilder withProperties(JaversCoreProperties javersProperties) { if (javersProperties.getMappingStyle() != null) { withMappingStyle(MappingStyle.valueOf(javersProperties.getMappingStyle().toUpperCase())); } if (javersProperties.getCommitIdGenerator() != null) { withCommitIdGenerator(CommitIdGenerator.valueOf(javersProperties.getCommitIdGenerator().toUpperCase())); } if (javersProperties.getPackagesToScan() != null) { withPackagesToScan(javersProperties.getPackagesToScan()); } if (javersProperties.isTypeSafeValues() != null) { withTypeSafeValues(javersProperties.isTypeSafeValues()); } if (javersProperties.getAlgorithm() != null) { withListCompareAlgorithm(ListCompareAlgorithm.valueOf(javersProperties.getAlgorithm().toUpperCase())); } if (javersProperties.isPrettyPrint() != null) { withPrettyPrint(javersProperties.isPrettyPrint()); } if (javersProperties.isInitialChanges() != null) { withInitialChanges(javersProperties.isInitialChanges()); } if (javersProperties.isTerminalChanges() != null) { withTerminalChanges(javersProperties.isTerminalChanges()); } withPrettyPrintDateFormats(javersProperties.getPrettyPrintDateFormats()); return this; } private void mapRegisteredClasses() { TypeMapper typeMapper = typeMapper(); for (ClientsClassDefinition def : clientsClassDefinitions.values()) { typeMapper.registerClientsClass(def); } } private TypeMapper typeMapper() { return getContainerComponent(TypeMapper.class); } private CoreConfigurationBuilder configurationBuilder() { return this.coreConfigurationBuilder; } private JsonConverterBuilder jsonConverterBuilder(){ return getContainerComponent(JsonConverterBuilder.class); } private Set bootAddOns() { Set additionalTypes = new HashSet<>(); for (ConditionalTypesPlugin plugin : conditionalTypesPlugins) { logger.info("loading "+plugin.getClass().getSimpleName()+" ..."); plugin.beforeAssemble(this); additionalTypes.addAll(plugin.getNewTypes()); AddOnsModule addOnsModule = new AddOnsModule(getContainer(), (Collection)plugin.getPropertyChangeAppenders()); addModule(addOnsModule); } return additionalTypes; } /** * boots JsonConverter and registers domain aware typeAdapters */ private void bootJsonConverter() { JsonConverterBuilder jsonConverterBuilder = jsonConverterBuilder(); jsonConverterBuilder.prettyPrint(coreConfiguration().isPrettyPrint()); addModule(new ChangeTypeAdaptersModule(getContainer())); addModule(new CommitTypeAdaptersModule(getContainer())); if (new RequiredMongoSupportPredicate().test(repository)) { jsonConverterBuilder.registerNativeGsonDeserializer(Long.class, new MongoLong64JsonDeserializer()); } jsonConverterBuilder.registerJsonTypeAdapters(getComponents(JsonTypeAdapter.class)); jsonConverterBuilder.registerNativeGsonDeserializer(Diff.class, new DiffTypeDeserializer()); JsonConverter jsonConverter = jsonConverterBuilder.build(); addComponent(jsonConverter); } private void bootDateTimeProvider() { if (dateProvider == null) { dateProvider = new DefaultDateProvider(); } addComponent(dateProvider); } private void bootRepository(){ CoreConfiguration coreConfiguration = coreConfiguration(); if (repository == null){ logger.info("using fake InMemoryRepository, register actual Repository implementation via JaversBuilder.registerJaversRepository()"); repository = new InMemoryRepository(); } repository.setJsonConverter( getContainerComponent(JsonConverter.class)); if (repository instanceof ConfigurationAware){ ((ConfigurationAware) repository).setConfiguration(coreConfiguration); } bindComponent(JaversRepository.class, repository); //JaversExtendedRepository can be created after users calls JaversBuilder.registerJaversRepository() addComponent(JaversExtendedRepository.class); } private T getClassDefinition(Class baseJavaClass) { return (T)clientsClassDefinitions.get(baseJavaClass); } private CoreConfiguration coreConfiguration() { return getContainerComponent(CoreConfiguration.class); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy