use of io.micronaut.data.intercept.DataInterceptor in project micronaut-coherence by micronaut-projects.
the class CoherenceDataIntroductionAdvice method findInterceptor.
@NonNull
private DataInterceptor<Object, Object> findInterceptor(@Nullable String dataSourceName, @NonNull Class<?> operationsType, @NonNull Class<?> interceptorType) {
DataInterceptor interceptor;
if (!RepositoryOperations.class.isAssignableFrom(operationsType)) {
throw new IllegalArgumentException("Repository type must be an instance of RepositoryOperations!");
}
Qualifier qualifier = Qualifiers.byName(dataSourceName);
RepositoryOperations datastore;
try {
datastore = (RepositoryOperations) beanLocator.getBean(operationsType, qualifier);
} catch (NoSuchBeanException e) {
// if there is no explicit configuration, use a DefaultCoherenceRepositoryOperations implementation
// using the default Coherence session
datastore = new DefaultCoherenceRepositoryOperations(dataSourceName, (ApplicationContext) beanLocator, (BeanContext) beanLocator);
((ApplicationContext) beanLocator).registerSingleton(RepositoryOperations.class, datastore, qualifier);
}
BeanIntrospection<Object> introspection = BeanIntrospector.SHARED.findIntrospections(ref -> interceptorType.isAssignableFrom(ref.getBeanType())).stream().findFirst().orElseThrow(() -> new DataAccessException("No Data interceptor found for type: " + interceptorType));
if (introspection.getConstructorArguments().length == 0) {
interceptor = (DataInterceptor) introspection.instantiate();
} else {
interceptor = (DataInterceptor) introspection.instantiate(datastore);
}
return interceptor;
}
use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.
the class MongoRawQueryMethodMatcher method methodMatchByFilterQuery.
private MethodMatch methodMatchByFilterQuery(DataMethod.OperationType operationType) {
return new MethodMatch() {
@Override
public MethodMatchInfo buildMatchInfo(MethodMatchContext matchContext) {
ParameterElement[] parameters = matchContext.getParameters();
ParameterElement entityParameter;
ParameterElement entitiesParameter;
if (parameters.length > 1) {
entityParameter = null;
entitiesParameter = null;
} else {
entityParameter = Arrays.stream(parameters).filter(p -> TypeUtils.isEntity(p.getGenericType())).findFirst().orElse(null);
entitiesParameter = Arrays.stream(parameters).filter(p -> TypeUtils.isIterableOfEntity(p.getGenericType())).findFirst().orElse(null);
}
Map.Entry<ClassElement, Class<? extends DataInterceptor>> entry = FindersUtils.resolveInterceptorTypeByOperationType(entityParameter != null, entitiesParameter != null, operationType, matchContext);
ClassElement resultType = entry.getKey();
Class<? extends DataInterceptor> interceptorType = entry.getValue();
boolean isDto = false;
if (resultType == null) {
resultType = matchContext.getRootEntity().getType();
} else {
if (resultType.hasAnnotation(Introspected.class)) {
if (!resultType.hasAnnotation(MappedEntity.class)) {
isDto = true;
}
}
}
MethodMatchInfo methodMatchInfo = new MethodMatchInfo(operationType, resultType, FindersUtils.getInterceptorElement(matchContext, interceptorType));
methodMatchInfo.dto(isDto);
buildRawQuery(matchContext, methodMatchInfo, entityParameter, entitiesParameter, operationType);
if (entityParameter != null) {
methodMatchInfo.addParameterRole(TypeRole.ENTITY, entityParameter.getName());
} else if (entitiesParameter != null) {
methodMatchInfo.addParameterRole(TypeRole.ENTITIES, entitiesParameter.getName());
}
return methodMatchInfo;
}
};
}
use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.
the class SaveOneMethodMatcher method match.
@Override
protected MethodMatch match(MethodMatchContext matchContext, java.util.regex.Matcher matcher) {
List<ParameterElement> parameters = matchContext.getParametersNotInRole();
if (parameters.size() == 0 || TypeUtils.isEntity(parameters.get(0).getGenericType()) || TypeUtils.isIterableOfEntity(parameters.get(0).getGenericType()) || !isValidSaveReturnType(matchContext, true)) {
return null;
}
return new MethodMatch() {
@Override
public MethodMatchInfo buildMatchInfo(MethodMatchContext matchContext) {
List<ParameterElement> parameters = matchContext.getParametersNotInRole();
SourcePersistentEntity rootEntity = matchContext.getRootEntity();
ClassElement returnType = matchContext.getReturnType();
if (TypeUtils.isReactiveOrFuture(returnType)) {
returnType = returnType.getFirstTypeArgument().orElse(null);
}
if (returnType == null || !TypeUtils.isNumber(returnType) && !rootEntity.getName().equals(returnType.getName())) {
throw new MatchFailedException("The return type of the save method must be the same as the root entity type: " + rootEntity.getName());
}
Set<String> requiredProps = rootEntity.getPersistentProperties().stream().filter(this::isRequiredProperty).map(PersistentProperty::getName).collect(Collectors.toSet());
ParameterElement[] parameterElements = rootEntity.getClassElement().getPrimaryConstructor().map(MethodElement::getParameters).orElse(null);
Map<String, ParameterElement> constructorArgs = new HashMap<>(10);
if (ArrayUtils.isNotEmpty(parameterElements)) {
for (ParameterElement parameterElement : parameterElements) {
constructorArgs.put(getParameterValue(parameterElement), parameterElement);
}
}
for (ParameterElement parameter : parameters) {
String name = getParameterValue(parameter);
ClassElement type = parameter.getGenericType();
SourcePersistentProperty prop = rootEntity.getPropertyByName(name);
ParameterElement constructorArg = constructorArgs.get(name);
if (prop == null && constructorArg == null) {
throw new MatchFailedException("Cannot save with non-existent property or constructor argument: " + name);
}
if (prop != null) {
String typeName = prop.getTypeName();
if (!type.isAssignable(typeName) && !typeName.equals(type.getName())) {
throw new MatchFailedException("Type mismatch. Found parameter of type [" + type.getName() + "]. Required property of type: " + typeName);
}
requiredProps.remove(name);
} else {
ClassElement argType = constructorArg.getGenericType();
String typeName = argType.getName();
if (!type.isAssignable(typeName) && !typeName.equals(type.getName())) {
throw new MatchFailedException("Type mismatch. Found parameter of type [" + type.getName() + "]. Required constructor argument of: " + typeName);
}
}
constructorArgs.remove(name);
}
if (!requiredProps.isEmpty()) {
throw new MatchFailedException("Save method missing required properties: " + requiredProps);
}
if (!constructorArgs.isEmpty()) {
Collection<ParameterElement> values = constructorArgs.values();
Set<String> names = values.stream().filter(pe -> {
SourcePersistentProperty prop = rootEntity.getPropertyByName(pe.getName());
return prop != null && prop.isRequired() && !prop.getType().isPrimitive();
}).map(p -> getParameterValue(p)).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(names)) {
throw new MatchFailedException("Save method missing required constructor arguments: " + names);
}
}
final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
Map.Entry<ClassElement, Class<? extends DataInterceptor>> e = FindersUtils.pickSaveOneInterceptor(matchContext, matchContext.getReturnType());
return new MethodMatchInfo(DataMethod.OperationType.INSERT, e.getKey(), getInterceptorElement(matchContext, e.getValue())).encodeEntityParameters(true).queryResult(matchContext.getQueryBuilder().buildInsert(annotationMetadataHierarchy, matchContext.getRootEntity()));
}
private boolean isRequiredProperty(SourcePersistentProperty pp) {
return pp.isRequired() && !ClassUtils.getPrimitiveType(pp.getTypeName()).isPresent();
}
};
}
use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.
the class DeleteCriteriaMethodMatch method build.
@Override
protected MethodMatchInfo build(MethodMatchContext matchContext) {
MethodMatchSourcePersistentEntityCriteriaBuilderImpl cb = new MethodMatchSourcePersistentEntityCriteriaBuilderImpl(matchContext);
PersistentEntityCriteriaDelete<Object> criteriaQuery = cb.createCriteriaDelete(null);
apply(matchContext, criteriaQuery.from(matchContext.getRootEntity()), criteriaQuery, cb);
Map.Entry<ClassElement, Class<? extends DataInterceptor>> entry = resolveReturnTypeAndInterceptor(matchContext);
ClassElement resultType = entry.getKey();
Class<? extends DataInterceptor> interceptorType = entry.getValue();
boolean optimisticLock = ((AbstractPersistentEntityCriteriaDelete<?>) criteriaQuery).hasVersionRestriction();
final AnnotationMetadataHierarchy annotationMetadataHierarchy = new AnnotationMetadataHierarchy(matchContext.getRepositoryClass().getAnnotationMetadata(), matchContext.getAnnotationMetadata());
QueryBuilder queryBuilder = matchContext.getQueryBuilder();
QueryModel queryModel = ((QueryModelPersistentEntityCriteriaQuery) criteriaQuery).getQueryModel();
QueryResult queryResult = queryBuilder.buildDelete(annotationMetadataHierarchy, queryModel);
return new MethodMatchInfo(DataMethod.OperationType.DELETE, resultType, getInterceptorElement(matchContext, interceptorType)).optimisticLock(optimisticLock).queryResult(queryResult);
}
use of io.micronaut.data.intercept.DataInterceptor in project micronaut-data by micronaut-projects.
the class FindMethodMatcher method match.
@Override
protected MethodMatch match(MethodMatchContext matchContext, java.util.regex.Matcher matcher) {
if (isCompatibleReturnType(matchContext)) {
return new QueryCriteriaMethodMatch(matcher) {
boolean hasIdMatch;
@Override
protected <T> void apply(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaQuery<T> query, SourcePersistentEntityCriteriaBuilder cb) {
super.apply(matchContext, root, query, cb);
if (query instanceof AbstractPersistentEntityCriteriaQuery) {
hasIdMatch = ((AbstractPersistentEntityCriteriaQuery<T>) query).hasOnlyIdRestriction();
}
}
@Override
protected Map.Entry<ClassElement, Class<? extends DataInterceptor>> resolveReturnTypeAndInterceptor(MethodMatchContext matchContext) {
Map.Entry<ClassElement, Class<? extends DataInterceptor>> e = super.resolveReturnTypeAndInterceptor(matchContext);
Class<? extends DataInterceptor> interceptorType = e.getValue();
ClassElement queryResultType = e.getKey();
if (isFindByIdQuery(matchContext, queryResultType)) {
if (interceptorType == FindOneInterceptor.class) {
interceptorType = FindByIdInterceptor.class;
} else if (interceptorType == FindOneAsyncInterceptor.class) {
interceptorType = FindByIdAsyncInterceptor.class;
} else if (interceptorType == FindOneReactiveInterceptor.class) {
interceptorType = FindByIdReactiveInterceptor.class;
}
}
return new AbstractMap.SimpleEntry<>(queryResultType, interceptorType);
}
private boolean isFindByIdQuery(@NonNull MethodMatchContext matchContext, @NonNull ClassElement queryResultType) {
return hasIdMatch && matchContext.supportsImplicitQueries() && queryResultType.getName().equals(matchContext.getRootEntity().getName()) && hasNoWhereAndJoinDeclaration(matchContext);
}
};
}
return null;
}
Aggregations