Skip to content

Commit

Permalink
HSEARCH-2046 Ignore attributes of @IndexEmbedded when applied on prim…
Browse files Browse the repository at this point in the history
…itive collections
  • Loading branch information
DavideD committed May 12, 2016
1 parent 3cb3f3f commit c1db510
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 29 deletions.
Expand Up @@ -102,6 +102,8 @@
*/
@SuppressWarnings( "deprecation" )
public class AnnotationMetadataProvider implements MetadataProvider {
private static final int INFINITE_DEPTH = Integer.MAX_VALUE;

private static final Log log = LoggerFactory.make();
private static final StringBridge NULL_EMBEDDED_STRING_BRIDGE = DefaultStringBridge.INSTANCE;
private static final String UNKNOWN_MAPPED_BY_ROLE = "";
Expand Down Expand Up @@ -999,7 +1001,7 @@ private ContainedInMetadata createContainedInMetadata(XProperty member) {
}

private void updateContainedInMetadata(ContainedInMetadataBuilder containedInMetadataBuilder, XProperty propertyWithContainedIn, String accessType) {
XClass memberReturnedType = propertyWithContainedIn.getElementClass();
XClass memberReturnedType = returnedType( propertyWithContainedIn );
String mappedBy = mappedBy( propertyWithContainedIn );
List<XProperty> returnedTypeProperties = memberReturnedType.getDeclaredProperties( accessType );
for ( XProperty property : returnedTypeProperties ) {
Expand Down Expand Up @@ -1298,7 +1300,7 @@ private FacetEncodingType determineFacetEncodingType(XProperty member, Facet fac
return facetEncodingType; // encoding type explicitly set
}

Class<?> indexedType = reflectionManager.toClass( member.getElementClass() );
Class<?> indexedType = reflectionManager.toClass( returnedType( member ) );
if ( ReflectionHelper.isIntegerType( indexedType ) ) {
facetEncodingType = FacetEncodingType.LONG;
}
Expand Down Expand Up @@ -1672,40 +1674,35 @@ private void checkForIndexedEmbedded(
return;
}

boolean elementCollection = isElementCollection( member );
if ( elementCollection ) {
// @IndexEmbedded used with @ElementCollection
logWarnings( member, indexedEmbeddedAnnotation );
}

parseContext.collectUnqualifiedCollectionRole( member.getName() );

int oldMaxLevel = parseContext.getMaxLevel();
int potentialLevel = depth( indexedEmbeddedAnnotation ) + parseContext.getLevel();
// This is really catching a possible int overflow. depth() can return Integer.MAX_VALUE, which then can
// overflow in case level > 0. Really this code should be rewritten (HF)
if ( potentialLevel < 0 ) {
potentialLevel = Integer.MAX_VALUE;
}
// HSEARCH-1442 recreating the behavior prior to PropertiesMetadata refactoring
int potentialLevel = elementCollection ? INFINITE_DEPTH : potentialLevel( parseContext, indexedEmbeddedAnnotation, member );
// HSEARCH-1442 recreating the behaviour prior to PropertiesMetadata refactoring
// not sure whether this is algorithmically correct though. @IndexedEmbedded processing should be refactored (HF)
if ( potentialLevel < oldMaxLevel ) {
parseContext.setMaxLevel( potentialLevel );
}
parseContext.incrementLevel();

XClass elementClass;
if ( void.class == indexedEmbeddedAnnotation.targetElement() ) {
elementClass = member.getElementClass();
}
else {
elementClass = reflectionManager.toXClass( indexedEmbeddedAnnotation.targetElement() );
}
XClass elementClass = elementCollection ? returnedType( member ) : elementClass( member, indexedEmbeddedAnnotation );
String localPrefix = elementCollection ? defaultPrefix( member ) : buildEmbeddedPrefix( prefix, indexedEmbeddedAnnotation, member );
boolean includeEmbeddedObjectId = elementCollection ? false : indexedEmbeddedAnnotation.includeEmbeddedObjectId();

if ( parseContext.getMaxLevel() == Integer.MAX_VALUE //infinite
if ( parseContext.getMaxLevel() == INFINITE_DEPTH
&& parseContext.hasBeenProcessed( elementClass ) ) {
throw log.detectInfiniteTypeLoopInIndexedEmbedded(
elementClass.getName(),
typeMetadataBuilder.getIndexedType().getName(),
buildEmbeddedPrefix( prefix, indexedEmbeddedAnnotation, member )
);
localPrefix );
}

String localPrefix = buildEmbeddedPrefix( prefix, indexedEmbeddedAnnotation, member );
PathsContext updatedPathsContext = updatePaths( localPrefix, pathsContext, indexedEmbeddedAnnotation );

boolean pathsCreatedAtThisLevel = false;
Expand Down Expand Up @@ -1752,7 +1749,7 @@ private void checkForIndexedEmbedded(
XClass previousClass = parseContext.getCurrentClass();
parseContext.setCurrentClass( elementClass );
boolean previousIncludeEmbeddedObjectId = parseContext.includeEmbeddedObjectId();
parseContext.setIncludeEmbeddedObjectId( indexedEmbeddedAnnotation.includeEmbeddedObjectId() );
parseContext.setIncludeEmbeddedObjectId( includeEmbeddedObjectId );
initializeClass(
embeddedTypeMetadataBuilder,
false,
Expand Down Expand Up @@ -1797,15 +1794,65 @@ else if ( log.isTraceEnabled() ) {
}
}

private void logWarnings(XProperty member, IndexedEmbedded indexedEmbeddedAnnotation) {
if ( isDepthSet( indexedEmbeddedAnnotation ) ) {
log.indexEmbeddedValueIgnored( member.getName(), "depth" );
}
if ( void.class != indexedEmbeddedAnnotation.targetElement() ) {
log.indexEmbeddedValueIgnored( member.getName(), "targetElement" );
}
if ( !isDefaultPrefix( indexedEmbeddedAnnotation ) ) {
log.indexEmbeddedValueIgnored( member.getName(), "prefix" );
}
if ( indexedEmbeddedAnnotation.includeEmbeddedObjectId() ) {
log.indexEmbeddedValueIgnored( member.getName(), "includeEmbeddedObjectId" );
}
}

private int potentialLevel(ParseContext parseContext, IndexedEmbedded indexedEmbeddedAnnotation, XProperty member) {
int potentialLevel = depth( indexedEmbeddedAnnotation ) + parseContext.getLevel();
// This is really catching a possible int overflow. depth() can return Integer.MAX_VALUE, which then can
// overflow in case level > 0. Really this code should be rewritten (HF)
if ( potentialLevel < 0 ) {
potentialLevel = INFINITE_DEPTH;
}
return potentialLevel;
}

private XClass elementClass(XProperty member, IndexedEmbedded indexedEmbeddedAnnotation) {
if ( void.class == indexedEmbeddedAnnotation.targetElement() ) {
return returnedType( member );
}
else {
return reflectionManager.toXClass( indexedEmbeddedAnnotation.targetElement() );
}
}

private XClass returnedType(XProperty member) {
return member.getElementClass();
}

private boolean isElementCollection(XProperty member) {
Annotation[] annotations = member.getAnnotations();
for ( Annotation annotation : annotations ) {
String type = annotation.annotationType().getName();
// Using String because the annotation class might not be on the classpath
if ( "javax.persistence.ElementCollection".equals( type ) ) {
return true;
}
}
return false;
}

private int depth(IndexedEmbedded embeddedAnn) {
if ( isDepthNotSet( embeddedAnn ) && embeddedAnn.includePaths().length > 0 ) {
if ( !isDepthSet( embeddedAnn ) && embeddedAnn.includePaths().length > 0 ) {
return 0;
}
return embeddedAnn.depth();
}

private boolean isDepthNotSet(IndexedEmbedded embeddedAnn) {
return Integer.MAX_VALUE == embeddedAnn.depth();
private boolean isDepthSet(IndexedEmbedded embeddedAnn) {
return INFINITE_DEPTH != embeddedAnn.depth();
}

private boolean isInPath(String localPrefix, PathsContext pathsContext, IndexedEmbedded embeddedAnn) {
Expand Down Expand Up @@ -1839,14 +1886,18 @@ private String buildEmbeddedPrefix(String prefix, IndexedEmbedded indexedEmbedde
String localPrefix = prefix;
if ( isDefaultPrefix( indexedEmbeddedAnnotation ) ) {
//default to property name
localPrefix += member.getName() + '.';
localPrefix += defaultPrefix( member );
}
else {
localPrefix += indexedEmbeddedAnnotation.prefix();
}
return localPrefix;
}

private String defaultPrefix(XProperty member) {
return member.getName() + '.';
}

private boolean isDefaultPrefix(IndexedEmbedded indexedEmbeddedAnnotation) {
return ".".equals( indexedEmbeddedAnnotation.prefix() );
}
Expand Down
Expand Up @@ -970,4 +970,7 @@ public interface Log extends BasicLogger {
@Message(id = 315, value = "Lazy remote analyzer %1$s is not initialized.")
SearchException lazyRemoteAnalyzerNotInitialized(LazyRemoteAnalyzer analyzer);

@LogMessage(level = Level.WARN)
@Message(id = 316, value = "The value for @IndexEmbedded#%2$s() on the property `%1$s` is ignored when the annotation is used with @ElementCollection")
void indexEmbeddedValueIgnored(String propertyName, String indexEmbeddedAttribute);
}
Expand Up @@ -104,11 +104,11 @@ public void testSearchNullEmbedded() throws Exception {
@Test
public void testSearchNullNumericEmbedded() throws Exception {
List<ArrayBridgeTestEntity> results =
findEmbeddedNullResults( "embeddedNum", ArrayBridgeTestEntity.NULL_EMBEDDED_NUMERIC, true );
findEmbeddedNullResults( "numericNullIndexed", ArrayBridgeTestEntity.NULL_EMBEDDED_NUMERIC, true );

assertNotNull( "No result found for an indexed collection", results );
assertEquals( "Unexpected number of results in a collection", 1, results.size() );
assertEquals( "Wrong result returned looking for a null in a collection of numeric", withNullEmbedded.getName(), results.get( 0 ).getName() );
assertEquals( "Wrong result returned looking for a null collection", withNullEmbedded.getName(), results.get( 0 ).getName() );
}

@Test
Expand Down
Expand Up @@ -113,7 +113,7 @@ public void testSearchNullEmbedded() throws Exception {
@Test
public void testSearchNullNumericEmbedded() throws Exception {
List<IterableBridgeTestEntity> results =
findEmbeddedNullResults( "embeddedNum", IterableBridgeTestEntity.NULL_EMBEDDED_NUMERIC, true );
findEmbeddedNullResults( "numericNullIndexed", IterableBridgeTestEntity.NULL_EMBEDDED_NUMERIC, true );

assertNotNull( "No result found for an indexed collection", results );
assertEquals( "Unexpected number of results in a collection", 1, results.size() );
Expand Down
Expand Up @@ -111,7 +111,7 @@ public void testSearchNullEmbedded() throws Exception {
@Test
public void testSearchNullNumericEmbedded() throws Exception {
List<MapBridgeTestEntity> results =
findEmbeddedNullResults( "embeddedNum", MapBridgeTestEntity.NULL_EMBEDDED_NUMERIC, true );
findEmbeddedNullResults( "numericNullIndexed", MapBridgeTestEntity.NULL_EMBEDDED_NUMERIC, true );

assertNotNull( "No result found for an indexed collection", results );
assertEquals( "Unexpected number of results in a collection", 1, results.size() );
Expand Down

0 comments on commit c1db510

Please sign in to comment.