Commit Graph

115 Commits

Author SHA1 Message Date
Oliver Gierke
b0eb0c47d2 DATACMNS-1377 - ConvertingPropertyAccessor now properly coverts values for property paths.
Previously, ConvertingPropertyAccessor did not override PersistentPropertyAccessor.setProperty(PersistentPropertyPath, Object), so that the target value had to be of the leaf property's type. We now implement that method and convert it into that type before invoking the super method.
2018-08-17 11:47:31 +02:00
Mark Paluch
7d3222320c DATACMNS-1364 - Store persistent properties in HashMap.
We now use HashMap to store persistent properties of a PersistentEntity. An entity is built in a single thread so no concurrent modification happens. Concurrent reads may happen during entity usage which is fine as the PersistentEntity is not changed anymore. Previously, we used ConcurrentReferenceHashMap defaulting to soft references. Soft references can be cleared at the discretion of the GC in response to memory demand. So a default ConcurrentReferenceHashMap is memory-sensitive and acts like a cache with memory-based eviction rules.

Persistent properties are not subject to be cached but elements of a PersistentEntity and cannot be recovered once cleared.

Original pull request: #304.
2018-08-15 09:50:48 +02:00
Oliver Gierke
14fbc11f00 DATACMNS-1366 - Introduce PersistentEntity.requiresPropertyPopulation().
The newly introduced method indicates whether any properties have to be populated to create instances of the entity. This is useful for objects that are completely initialized through their constructors as converters then can avoid iterating over all properties just to find out none of them have to be populated.
2018-08-08 13:16:05 +02:00
Oliver Gierke
57d0b322e6 DATACMNS-1359 - Improved exception message for missing accessors and getters.
The exception messages used in the PersistentProperty.getRequired(Getter|Setter|Wither|Field)(…) now mention the name of the property that's offending.
2018-08-06 12:45:43 +02:00
Oliver Gierke
3c2522df9a DATACMNS-1322 - Added @Immutable to allow users to express a persistent entity to be considered immutable.
This is needed for downstream projects that attempt to merge persistent entity instances and previously didn't have a chance to detect that an object had to be set as-is instead of being merged recursively.
2018-07-12 10:26:16 +02:00
Oliver Gierke
1f4d494f83 DATACMNS-1322 - Generified PersistentPropertyAccessor API.
PersistentPropertyAccessor is now generic to be able to retain the type information about the object it was created for and the return type of ….getBean(). Adapted client APIs.
2018-07-12 10:23:17 +02:00
Oliver Gierke
d1ebfcfc5e DATACMNS-1322 - Add support for immutable entities in PersistentPropertyAccessor.setProperty(PersistentPropertyPath, Object).
As setting a PersistentProperty can actually change the object that the property is changed on, we now recursively traverse property paths up as longs as the setting of the property results in the bean not being replaced.
2018-07-04 16:59:51 +02:00
Mark Paluch
79119000bb DATACMNS-1322 - Add support for Kotlin's copy(…) method.
We now support updating of immutable Kotlin data objects by creating new copies through Kotlin's copy method that is generated along with data classes and immutable properties.

data class DataClassKt(val id: String) {
}

data class ExtendedDataClassKt(val id: String, val name: String) {
}
2018-07-04 16:59:51 +02:00
Mark Paluch
1ea65f3130 DATACMNS-1322 - Detect wither methods.
We now detect withher methods (withId(…)) that create a new object instance that contains the new property value. We support those wither methods to create new object instances from property updates. Classes following a wither pattern declare a withXXX(…) method that accepts the property value and return a new, instance of its own type associated with the property value. Along with this change we removed the ability to update final fields that worked by accident using reflection.

class ValueClass {
	@Wither String id;
}

class ValueClass {
	final String id;

	ValueClass withId(String id) {
		return new ValueClass(id);
	}
}
2018-07-04 16:59:51 +02:00
Oliver Gierke
5f87c67668 DATACMNS-1304 - Polishing.
Moved test cases into PropertyPathUnit test so that they're closer to the implementation. Switched to Introspector.decapitalize(…) to follow the Java Beans Specification regarding the handling of all-uppercase properties.

Original pull request: #289.
2018-06-05 18:34:12 +02:00
Oliver Gierke
fc2135df3d DATACMNS-1333 - Unified is-new-detection in PersistentEntity.isNew(…).
PersistentEntity now exposes an ….isNew(…) method that exposes the same detection algorithm previously exposed through MappingContextIsNewStrategyFactory (Persistable in favor of the version property in favor of an identifier lookup). MappingContextIsNewStrategyFactory  has been refactored to return an ad-hoc strategy to delegate to the newly introduced method.

The core message to implementing modules is that they should now prefer PersistentEntityInformation within their RepositoryFactorySupport implementation and move all customizations made in the store-specific EntityInformation implementation in PersistentEntity.
2018-06-01 13:50:28 +02:00
Oliver Gierke
7ab2c84ea8 DATACMNS-1318 - Polishing.
Moved to newly introduced varargs-based factory method for PersistentEntities where applicable.
2018-05-30 21:39:56 +02:00
Oliver Gierke
61e489b67e DATACMNS-1318 - Allow inspection of a reference's ultimate target entity.
We now expose what type or PersistentEntity an association points to by trying to match the association's type to identifier types to entities. In case multiple matches are found, we require the user to explicitly declare the target type via @Reference.

Introduced PersistentEntities.of(…) for convenience.
2018-05-30 21:39:54 +02:00
Oliver Gierke
7d8539d83c DATACMNS-1326 - PersistentPropertyInspectingIsNewStrategy now considers primitive type's defaults.
PersistentPropertyInspectingIsNewStrategy now considers entities with primitive default identifier values new.
2018-05-18 23:46:48 +02:00
Oliver Gierke
865163d466 DATACMNS-1325 - Added dedicated identifier accessor for Persistable entities.
BasicPersistentEntity now returns a dedicated IdentifierAccessor that uses Persistable.getId() in case the entity implements Persistable.
2018-05-18 23:46:48 +02:00
Mark Paluch
2d24acf9de DATACMNS-1294 - Consider java.time types simple ones.
We now consider all types in the java.time package as simple types to prevent deep reflective access. We are already excluding java.lang types for the same reason.

Original pull request: #286.
2018-04-18 18:53:59 +02:00
Oliver Gierke
ac324b22a5 DATACMNS-1275 - Introduced MappingContext.findPersistentPropertyPaths(Class<?>, Predicate<P>).
MappingContext now exposes a method to detect all property paths pointing to properties matching a given predicate.

Extracted PersistentPropertyPath creation into a dedicated factory class so that it can be tested individually. DefaultPersistentPropertyPath now exposes a ….containsPropertyOfType(…) to detect whether we've already processed a particular type in the path. Also applied a bit of Java 8 and Lombok polish.

InvalidPersistentPropertyPath now collects suggested alternatives to create a better exception message. PersistentEntities now allows to map over a MappingContext and PersistentEntity that a given type is corresponding to. Streamable now exposes an ….isEmpty(). Removed references to equivalent methods implemented in subtypes.
2018-04-09 14:31:20 +02:00
Oliver Gierke
06b0dab536 DATACMNS-1285 - PropertyPath now limits the depth of its parsing to 1000 segments. 2018-04-03 19:27:16 +02:00
Oliver Gierke
0f174f6867 DATACMNS-1278 - Make sure that SimpleTypeHolder always treats enums as simple.
We now explicitly check for an enum type in SimpleTypeHolder.isSimpleType(…) and resort to true immediately. Before that an enum implementing an interface could have seen a false for the actual enum type in case the interface type had been checked first and (correctly) produced a false. In the check for the actual enum type, depending on the iteration order through the cached values we could've hit the cached false for the interface or the cached true value for Enum.
2018-03-12 10:47:26 +01:00
Mark Paluch
51e7e1b7f5 DATACMNS-1240 - Update copyright years to 2018.
Also, remove some trailing whitespaces and align outdated license header format.
2018-01-08 16:04:34 +01:00
Oliver Gierke
e2bac30be4 DATACMNS-1214 - Fixed AbstractMappingContext.getPersistentEntity(PersistentProperty) to now return null for non-entities.
Previously, a call to AbstractMappingContext.getPersistentEntity(PersistentProperty) would've added potentially leniently added the type of the given PersistentProperty, no matter whether it's actually considered to be an entity in the first place. We now defensively check for whether the given property is to be considered an entity (taking potentially registered converters into account) before the potentially entity-creating by-type lookup.
2017-11-16 16:36:27 +01:00
Oliver Gierke
24c1b823c6 DATACMNS-1210 - Polishing.
More fixes of imports. Removed obsolete generics in constructor expressions. Removed a couple of compiler warnings in test cases. Removed assumption for test case to only run on JDK 9.

Original pull request: #259.
2017-11-14 17:59:43 +01:00
Christoph Strobl
309cdc5e43 DATACMNS-1210 - Fix concurrency issue in BasicPersitentEntity.
Make sure to use concurrent collection implementations for properties holding mutable state. Especially the ones making use of computeIfAbsent(…).

Usage of ConcurrentReferenceHashMap allows us to move on without additional changes as it allows to store null values, whereas ConcurrentHashMap would require us to store explicit NullValue placeholders for such cases, potentially causing trouble in downstream store specific projects.

JMH Benchmarks done with the Spring Data MongoDB mapping layer showed a potential performance loss of up to 5%. However a comparison between ConcurrentReferenceHashMap and ConcurrentHashMap did not show any significant difference in performance.

Original pull request: #259.
2017-11-14 17:59:16 +01:00
Oliver Gierke
d8cea8ba1c DATACMNS-1208 - AbstractMappingContext.hasPersistentEntityFor(…) now properly considers cached absence.
AbstractMappingContext.hasPersistentEntityFor(…) now also properly consideres the empty Optional as non-presence as that is held to allow to distinguish between a type completely unkown to the context, or already known but not considered a persistent entity.

Related pull request: #258.
2017-11-14 10:01:32 +01:00
Oliver Gierke
baee26e5e7 DATACMNS-1180 - Fixed accessor lookup for generic properties.
In AbstractPersistentProperty, we now resolve the potentially generic return and parameter types of getters and setters. To achieve that Property has now been made aware of the actual owning type.
2017-10-27 10:40:38 +02:00
Mark Paluch
a13fc238d3 DATACMNS-1201 - Support generated property accessors for types in default packages.
We now support generated property accessors for types that reside in the default package.

Original pull request: #256.
2017-10-24 22:34:30 +02:00
Oliver Gierke
4bd8a3cfc3 DATACMNS-1199 - Added PropertyPath.nested(…).
This allows to obtain a nested property path based on a currently available one.
2017-10-19 12:40:53 +02:00
Oliver Gierke
b3e1601bc6 DATACMNS-1198 - Added PropertyPath.getLeafType() to expose leaf-property type. 2017-10-19 12:25:00 +02:00
Mark Paluch
cc0ab54c38 DATACMNS-1171 - Do not create PersistentEntity for unsupported Kotlin classes.
We now reject unsupported Kotlin classes from the MappingContext by default by not creating persistent entities.

Original pull request: #245.
2017-09-25 12:23:35 +02:00
Jens Schauder
ea03388a7c DATACMNS-1161 - Renamed PersistentProperty.getPersitentEntityType(…) to ….getPersitentEntityTypes(…).
The new name currently delegates to old version, so classes only implementing the old method still work. Old name is deprecated.

Original pull request: #243.
2017-09-21 17:46:28 +02:00
Mark Paluch
3a2b6b601b DATACMNS-1141 - Add missing NonNullApi and Nullable annotations.
Add Nullable annotation to ParsingUtils, Sort.Order and PropertyValueProvider.

Add getRequiredAnnotation(…) to PersistentEntity and PersistentProperty to provide methods returning required, non-null annotations.
2017-08-28 13:32:15 +02:00
Mark Paluch
22b37800ec DATACMNS-1126 - Add class-generating entity instantiation support for Kotlin.
We now discover Kotlin constructors and apply parameter defaulting to allow construction of immutable value objects. Constructor discovery uses primary constructors by default and considers PersistenceConstructor annotations.

KotlinClassGeneratingEntityInstantiator can instantiate Kotlin classes with default parameters by resolving the synthetic constructor. Null values translate to parameter defaults.

class Person(val firstname: String = "Walter") {
}

class Address(val street: String, val city: String) {

	@PersistenceConstructor
	constructor(street: String = "Unknown", city: String = "Unknown", country: String) : this(street, city)
}

Original pull request: #233.
2017-08-25 13:04:28 +02:00
Oliver Gierke
fb9d38d79c DATACMNS-1139 - AbstractPersistentProperty.getRawType() now correctly resolves generics.
We're now favoring the generic TypeInformation over trying to resolve the property type via field or PropertyDescriptor as only the former does proper generic type resolution.
2017-08-14 14:06:16 +02:00
Oliver Gierke
049970874d DATACMNS-1114 - Introduced usage of nullable annotations for API validation.
Marked all packages with Spring Frameworks @NonNullApi. Added Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fixed Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances.

Removed null handling from converters for JodaTime and ThreeTenBP. Introduced factory methods Page.empty() and Page.empty(Pageable). Introduced default methods getRequiredGetter(), …Setter() and …Field() on PersistentProperty to allow non-nullable lookups of members. The same for TypeInformation.getrequiredActualType(), …SuperTypeInformation().

Tweaked PersistentPropertyCreator.addPropertiesForRemainingDescriptors() to filter unsuitable PropertyDescriptors before actually trying to create a Property instance from them as the new stronger nullability requirements would cause exceptions downstream.

Lazy.get() now expects a non-null return value. Clients being able to cope with null need to call ….orElse(…).

Original pull request: #232.
2017-07-24 10:47:28 +02:00
Mark Paluch
86945f81d1 DATACMNS-1122 - Improve message for absent required property in PersistentEntity.getRequiredPersistentProperty(…).
Exception message now contains the property name.
2017-07-21 08:54:39 +02:00
Oliver Gierke
5e4cac308e DATACMNS-1120 - Introduced caching of PropertyPath instances. 2017-07-20 13:38:43 +02:00
Oliver Gierke
dfcb9f77a4 DATACMNS-1116 - AbstractMappingContext now caches PersistentPropertyPaths.
As the calculation of a PersistentPropertyPath instances is rather expensive and they're heavily used in downstream mapping operations (e.g. query and fields mapping in MongoDB) we now cache the instances created per base type and property path.
2017-07-19 13:45:41 +02:00
Christoph Strobl
f6a6565638 DATACMNS-1101 - Remove getPersistentProperties/Associations from PersistentEntity.
Remove lately introduced getPersistentProperties / getAssociations and rather extend Iterable<? extends PersistentProperty<P>>
2017-07-04 14:30:45 +02:00
Christoph Strobl
88ac1fc165 DATACMNS-1101 - Polishing.
Move MappingException from o.s.d.mapping.model to o.s.d.mapping package and use it for getRequired* methods in MappingContext instead of throwing IllegalArgumentException. Further on we’ve consolidated usage of IllegalArgumentException and IllegalStateException. Along that IllegalMappingException was removed in favor or MappingException.

BasicPersistentEntity now looks up all properties by annotation instead of just returning the first one found. We’ve kept the original methods behavior and updated the comment as well as introduced getPersistentProperties returning all matching properties.
2017-07-04 14:30:45 +02:00
Mark Paluch
2064c72a85 DATACMNS-1101 - Remove Optional from PersistentProperty.getComponentType(…)/getMapValueType(…). 2017-07-04 14:30:44 +02:00
Mark Paluch
eb9854f18f DATACMNS-1101 - Cache positive and negative simple type hits. 2017-07-04 14:30:44 +02:00
Mark Paluch
6c65c02e78 DATACMNS-1101 - Remove Optional from mapping/convert use except for caching of absence and computations that are used to populate caches. 2017-07-04 14:30:42 +02:00
Mark Paluch
74fbe13f54 DATACMNS-1101 - Reduce Optional usage in convert/mapping packages.
Reducing Optional usage that lies on hot code paths for object mapping.
2017-07-04 14:30:42 +02:00
Roman Rodov
cabfa287cb DATACMNS-1082 - Skip synthetic constructors.
Constructor discovery no longer considers synthetic constructors for preferred constructor.

Original pull request: #225
2017-06-07 08:45:28 +02:00
Jens Schauder
42621086fe DATACMNS-1026 - ExtensionAwareEvaluationContextProvider now returns all overloaded methods as functions.
All overloaded methods are now available in SPeL expressions. Among methods with identical argument list from different sources in the same extension (extension, root object, aliases) the last one in the order in parens wins. If there is more than one method for an application the following rules are applied: if there is one method with exact matching types in the argument list it is used, otherwise an exception is thrown.

Original pull request: #217.
2017-05-17 16:20:38 +02:00
Oliver Gierke
233fde36b5 DATACMNS-1035 - Moved CustomConversions to Spring Data Commons.
Extracted CustomConversions — whose code has largely been duplicated between the MongoDB, Couchbase and Cassandra modules — into Spring Data Commons. Store-specific extensions can now be contributed via a StoreConversions value type that carries both, store-specific default converters as well as a store-specific SimpleTypeHolder to augment the default list of simple types.

Removed SimpleTypeHolders public default constructor in favour of a protected one and a static DEFAULT instance for plain references.

Original pull request: #210.
2017-04-21 16:49:00 +02:00
Oliver Gierke
6b5b65804e DATACMNS-1015 - Introduced IdentifierAccessor.getRequiredIdentifier().
The new method allows to look up identifiers and immediately fail in the case of absence. Introduced the method as default method but also a new base type TargetAwareIdentifierAccessor to throw an exception with more context, i.e. the actual target bean we try to look up the identifier on.
2017-03-24 11:57:57 +01:00
Oliver Gierke
790bfc6991 DATACMNS-867 - Upgrade to Mockito 2.7. 2017-03-24 08:00:48 +01:00
Oliver Gierke
5f117a00a3 DATACMNS-867 - Polishing of Property value type in mapping package. 2017-03-24 08:00:48 +01:00
Oliver Gierke
7ac12c3c3d DATACMNS-867 - BasicPersistentEntity now rejects null Association.
Related ticket: DATACMNS-934.
2017-03-24 08:00:47 +01:00