Refactor MimeType/MediaType specificity
This commit makes several changes to MimeType and MediaType related to the topic of specificity. This commit deprecates the MimeType and MediaType Comparators. Comparators require a transitive relationship, and the desired order for these types is not transitive (see #27488). Instead, this commit introduces two new MimeType methods: isMoreSpecific and isLessSpecific, both of which return booleans. MediaType overrides these methods to include the quality factor (q) in the comparison. All MediaType sorting methods have been deprecated in favor of MimeTypeUtils::sortBySpecificity. This sorting method now uses MimeType::isLessSpecific in combination a bubble sort algorithm (which does not require a transitive compare function). Closes gh-27580
This commit is contained in:
committed by
Arjen Poutsma
parent
a7789db067
commit
6d9136013e
@@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.testfixture.io.SerializationTestUtils;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -240,6 +241,44 @@ public class MediaTypeTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMoreSpecific() {
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audioBasic07 = new MediaType("audio", "basic", 0.7);
|
||||
MediaType audioBasic03 = new MediaType("audio", "basic", 0.3);
|
||||
|
||||
assertThat(audioBasic.isMoreSpecific(audio)).isTrue();
|
||||
assertThat(audio.isMoreSpecific(audioBasic)).isFalse();
|
||||
|
||||
assertThat(audio.isMoreSpecific(audioBasic07)).isTrue();
|
||||
assertThat(audioBasic07.isMoreSpecific(audio)).isFalse();
|
||||
|
||||
assertThat(audioBasic07.isMoreSpecific(audioBasic03)).isTrue();
|
||||
assertThat(audioBasic03.isMoreSpecific(audioBasic07)).isFalse();
|
||||
|
||||
assertThat(audioBasic.isMoreSpecific(MediaType.TEXT_HTML)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLessSpecific() {
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audioBasic07 = new MediaType("audio", "basic", 0.7);
|
||||
MediaType audioBasic03 = new MediaType("audio", "basic", 0.3);
|
||||
|
||||
assertThat(audioBasic.isLessSpecific(audio)).isFalse();
|
||||
assertThat(audio.isLessSpecific(audioBasic)).isTrue();
|
||||
|
||||
assertThat(audio.isLessSpecific(audioBasic07)).isFalse();
|
||||
assertThat(audioBasic07.isLessSpecific(audio)).isTrue();
|
||||
|
||||
assertThat(audioBasic07.isLessSpecific(audioBasic03)).isFalse();
|
||||
assertThat(audioBasic03.isLessSpecific(audioBasic07)).isTrue();
|
||||
|
||||
assertThat(audioBasic.isLessSpecific(MediaType.TEXT_HTML)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificityComparator() throws Exception {
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
@@ -470,4 +509,33 @@ public class MediaTypeTests {
|
||||
assertThat(original).isEqualTo(deserialized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortBySpecificity() {
|
||||
MediaType audioBasic = new MediaType("audio", "basic");
|
||||
MediaType audio = new MediaType("audio");
|
||||
MediaType audio03 = new MediaType("audio", "*", 0.3);
|
||||
MediaType audio07 = new MediaType("audio", "*", 0.7);
|
||||
MediaType audioBasicLevel = new MediaType("audio", "basic", Collections.singletonMap("level", "1"));
|
||||
MediaType all = MediaType.ALL;
|
||||
|
||||
List<MediaType> expected = new ArrayList<>();
|
||||
expected.add(audioBasicLevel);
|
||||
expected.add(audioBasic);
|
||||
expected.add(audio);
|
||||
expected.add(all);
|
||||
expected.add(audio07);
|
||||
expected.add(audio03);
|
||||
|
||||
List<MediaType> result = new ArrayList<>(expected);
|
||||
Random rnd = new Random();
|
||||
// shuffle & sort 10 times
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Collections.shuffle(result, rnd);
|
||||
MimeTypeUtils.sortBySpecificity(result);
|
||||
|
||||
assertThat(result).containsExactlyElementsOf(expected);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user