use of org.glassfish.jersey.message.WriterModel in project jersey by jersey.
the class MethodSelectingRouter method determineResponseMediaType.
/**
* Determine the {@link MediaType} of the {@link Response} based on writers suitable for the given entity class,
* pre-selected method and acceptable media types.
*
* @param entityClass entity class to determine the media type for.
* @param entityType entity type for writers.
* @param selectedMethod pre-selected (invoked) method.
* @param acceptableMediaTypes acceptable media types from request.
* @return media type of the response.
*/
private MediaType determineResponseMediaType(final Class<?> entityClass, final Type entityType, final RequestSpecificConsumesProducesAcceptor selectedMethod, final List<AcceptableMediaType> acceptableMediaTypes) {
// Return pre-selected MediaType.
if (usePreSelectedMediaType(selectedMethod, acceptableMediaTypes)) {
return selectedMethod.produces.combinedType;
}
final ResourceMethod resourceMethod = selectedMethod.methodRouting.method;
final Invocable invocable = resourceMethod.getInvocable();
// Entity class can be null when considering HEAD method || empty entity.
final Class<?> responseEntityClass = entityClass == null ? invocable.getRawRoutingResponseType() : entityClass;
final Method handlingMethod = invocable.getHandlingMethod();
// Media types producible by method.
final List<MediaType> methodProducesTypes = !resourceMethod.getProducedTypes().isEmpty() ? resourceMethod.getProducedTypes() : Collections.singletonList(MediaType.WILDCARD_TYPE);
// Applicable entity providers
final List<WriterModel> writersForEntityType = workers.getWritersModelsForType(responseEntityClass);
CombinedMediaType selected = null;
for (final MediaType acceptableMediaType : acceptableMediaTypes) {
for (final MediaType methodProducesType : methodProducesTypes) {
if (!acceptableMediaType.isCompatible(methodProducesType)) {
// no need to go deeper if acceptable and method produces type are incompatible
continue;
}
// Use writers suitable for entity class to determine the media type.
for (final WriterModel model : writersForEntityType) {
for (final MediaType writerProduces : model.declaredTypes()) {
if (!writerProduces.isCompatible(acceptableMediaType) || !methodProducesType.isCompatible(writerProduces)) {
continue;
}
final CombinedMediaType.EffectiveMediaType effectiveProduces = new CombinedMediaType.EffectiveMediaType(MediaTypes.mostSpecific(methodProducesType, writerProduces), false);
final CombinedMediaType candidate = CombinedMediaType.create(acceptableMediaType, effectiveProduces);
if (candidate != CombinedMediaType.NO_MATCH) {
// Look for a better compatible worker.
if (selected == null || CombinedMediaType.COMPARATOR.compare(candidate, selected) < 0) {
if (model.isWriteable(responseEntityClass, entityType, handlingMethod.getDeclaredAnnotations(), candidate.combinedType)) {
selected = candidate;
}
}
}
}
}
}
}
// Found media type for current writer.
if (selected != null) {
return selected.combinedType;
}
// so it can be written.
return selectedMethod.produces.combinedType;
}
Aggregations