Skip to content

Commit

Permalink
HSEARCH-4142 Check required type in IdentifierValueConverter
Browse files Browse the repository at this point in the history
  • Loading branch information
fax4ever committed Mar 1, 2021
1 parent 78b46b0 commit e9de87e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 0 deletions.
Expand Up @@ -8,6 +8,7 @@

import org.hibernate.search.engine.backend.types.converter.runtime.spi.ToDocumentIdentifierValueConvertContext;
import org.hibernate.search.engine.backend.types.converter.runtime.spi.ToDocumentIdentifierValueConvertContextExtension;
import org.hibernate.search.util.common.SearchException;

/**
* A converter from a source identifier value to a target value that should be used as a document identifier
Expand Down Expand Up @@ -39,6 +40,14 @@ public interface DocumentIdentifierValueConverter<I> {
*/
String convertToDocumentUnknown(Object value, ToDocumentIdentifierValueConvertContext context);

/**
* @param requiredType the required type
* @throws SearchException if the expected actual type is not a subclass of the required type
*/
default void requiresType(Class<?> requiredType) {
// no check by default
}

/**
* @param other Another {@link DocumentIdentifierValueConverter}, never {@code null}.
* @return {@code true} if the given object behaves exactly the same as this object, i.e. its
Expand Down
Expand Up @@ -6,10 +6,16 @@
*/
package org.hibernate.search.engine.backend.types.converter.spi;

import java.lang.invoke.MethodHandles;

import org.hibernate.search.engine.backend.types.converter.runtime.spi.ToDocumentIdentifierValueConvertContext;
import org.hibernate.search.engine.logging.impl.Log;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;

public final class StringDocumentIdentifierValueConverter implements DocumentIdentifierValueConverter<String> {

private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

@Override
public String convertToDocument(String value, ToDocumentIdentifierValueConvertContext context) {
return value;
Expand All @@ -20,6 +26,13 @@ public String convertToDocumentUnknown(Object value, ToDocumentIdentifierValueCo
return (String) value;
}

@Override
public void requiresType(Class<?> requiredType) {
if ( !String.class.isAssignableFrom( requiredType ) ) {
throw log.wrongRequiredIdentifierType( requiredType, String.class );
}
}

@Override
public boolean isCompatibleWith(DocumentIdentifierValueConverter<?> other) {
return getClass().equals( other.getClass() );
Expand Down
Expand Up @@ -391,6 +391,7 @@ BeanNotFoundException unableToResolveToClassName(@FormatWith(ClassFormatter.clas
+ " Otherwise, use a valid bean retrieval prefix among the following: %3$s.")
BeanNotFoundException invalidBeanRetrieval(String beanReference, String invalidPrefix,
List<String> validPrefixes, @Cause Exception e);

@Message(id = ID_OFFSET + 93,
value = "Named predicate name '%1$s' is invalid: field names cannot be null or empty.")
SearchException relativeNamedPredicateNameCannotBeNullOrEmpty(String relativeNamedPredicateName,
Expand All @@ -401,4 +402,10 @@ SearchException relativeNamedPredicateNameCannotBeNullOrEmpty(String relativeNam
+ " Remove the dot from your named predicate name.")
SearchException relativeNamedPredicateNameCannotContainDot(String relativeNamedPredicateName,
@Param EventContext context);

@Message(id = ID_OFFSET + 95, value = "The required identifier type '%1$s'"
+ " does not match the actual identifier type '%2$s':"
+ " the required identifier must be a superclass of the actual identifier.")
SearchException wrongRequiredIdentifierType(@FormatWith(ClassFormatter.class) Class<?> requiredIdentifierType,
@FormatWith(ClassFormatter.class) Class<?> actualIdentifierType);
}
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.search.mapper.pojo.bridge.runtime.impl;

import java.lang.invoke.MethodHandles;
import java.util.Optional;

import org.hibernate.search.engine.backend.types.converter.spi.DocumentIdentifierValueConverter;
Expand All @@ -15,9 +16,13 @@
import org.hibernate.search.mapper.pojo.bridge.IdentifierBridge;
import org.hibernate.search.mapper.pojo.bridge.runtime.IdentifierBridgeToDocumentIdentifierContext;
import org.hibernate.search.mapper.pojo.bridge.runtime.spi.BridgeMappingContext;
import org.hibernate.search.mapper.pojo.logging.impl.Log;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;

public final class PojoIdentifierBridgeDocumentIdentifierValueConverter<I> implements DocumentIdentifierValueConverter<I> {

private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private final IdentifierBridge<I> bridge;
private final Class<I> expectedValueType;

Expand All @@ -42,6 +47,13 @@ public String convertToDocumentUnknown(Object value, ToDocumentIdentifierValueCo
return convertToDocument( expectedValueType.cast( value ), context );
}

@Override
public void requiresType(Class<?> requiredType) {
if ( !expectedValueType.isAssignableFrom( requiredType ) ) {
throw log.wrongRequiredIdentifierType( requiredType, expectedValueType );
}
}

@Override
public boolean isCompatibleWith(DocumentIdentifierValueConverter<?> other) {
if ( other == null || !getClass().equals( other.getClass() ) ) {
Expand Down
Expand Up @@ -558,4 +558,10 @@ void arbitraryMemberSelection(@FormatWith(PojoTypeModelFormatter.class) PojoRawT
value = "Invalid entity name '%1$s' in an indexing event: this entity does not exist or is not indexed.")
SearchException nonIndexedTypeInIndexingEvent(String entityName);

@Message(id = ID_OFFSET + 90, value = "The required identifier type '%1$s'"
+ " does not match the actual identifier type '%2$s':"
+ " the required identifier must be a superclass of the actual identifier.")
SearchException wrongRequiredIdentifierType(@FormatWith(ClassFormatter.class) Class<?> requiredIdentifierType,
@FormatWith(ClassFormatter.class) Class<?> actualIdentifierType);

}

0 comments on commit e9de87e

Please sign in to comment.