Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed order and ignore duplicates on parse #28

Merged
merged 1 commit into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions src/main/java/wtf/g4s8/mime/MimeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -62,15 +65,30 @@ static MimeType of(final CharSequence src) {
* @since 2.1
*/
static Collection<MimeType> parse(final CharSequence src) {
final Predicate<? super MimeType> pred = new Predicate<MimeType>(){
final Set<String> types = new HashSet<>();

@Override
public boolean test(MimeType type) {
final String key = String.format("%s/%s", type.type(), type.subtype());
final boolean check;
if (types.contains(key)) {
check = false;
} else {
types.add(key);
check = true;
}
return check;
}
};
return Arrays.stream(src.toString().split(","))
.map(String::trim)
.map(MimeTypeOfString::new)
.sorted(
(left, right) -> Float.compare(
right.param("q").map(Float::parseFloat).orElse(0F),
left.param("q").map(Float::parseFloat).orElse(0F)
)
).collect(Collectors.toList());
MimeTypeComparators.BY_QUALIFIER
.thenComparing(MimeTypeComparators.BY_TYPE)
.thenComparing(MimeTypeComparators.BY_SUBTYPE)
).filter(pred).collect(Collectors.toList());
}

/**
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/wtf/g4s8/mime/MimeTypeComparators.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* The MIT License (MIT) Copyright (c) 2017-2021 Kirill Ch. <g4s8.public@gmail.com>
* https://github.com/g4s8/mime/LICENSE.txt
*/
package wtf.g4s8.mime;

import java.util.Comparator;

/**
* MIME types comparators.
* @since 2.2
*/
public enum MimeTypeComparators implements Comparator<MimeType> {
BY_QUALIFIER(
(left, right) -> Float.compare(
right.param("q").map(Float::parseFloat).orElse(1F),
left.param("q").map(Float::parseFloat).orElse(1F)
)
),
BY_TYPE((left, right) -> compareTypes(left.type(), right.type())),
BY_SUBTYPE((left, right) -> compareTypes(left.subtype(), right.subtype()));

/**
* Origin comparator.
*/
private final Comparator<? super MimeType> origin;

/**
* Private enum constructor.
* @param origin
*/
private MimeTypeComparators(final Comparator<? super MimeType> origin) {
this.origin = origin;
}

@Override
public int compare(MimeType left, MimeType right) {
return this.origin.compare(left, right);
}

/**
* Parse MIME types, pay attetion to wildcards.
* @param left Left type
* @param right Right type
* @return Compare result
*/
private static int compareTypes(final String left, final String right) {
final int res;
if (left.equals("*")) {
if (right.equals("*")) {
res = 0;
} else {
res = 1;
}
} else {
res = left.compareTo(right);
}
return res;
}
}
1 change: 0 additions & 1 deletion src/main/java/wtf/g4s8/mime/MimeTypeOfString.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ final class MimeTypeOfString implements MimeType {
);
}


/**
* Source string.
*/
Expand Down
55 changes: 55 additions & 0 deletions src/main/java/wtf/g4s8/mime/MimeTypeSimple.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* The MIT License (MIT) Copyright (c) 2017-2021 Kirill Ch. <g4s8.public@gmail.com>
* https://github.com/g4s8/mime/LICENSE.txt
*/
package wtf.g4s8.mime;

import java.util.Collections;
import java.util.Optional;
import java.util.Set;

/**
* Simple mime type without params.
*/
public final class MimeTypeSimple implements MimeType {

/**
* Type.
*/
private final String tpe;

/**
* Subtype.
*/
private final String sub;

/**
* New simple MIME-type.
* @param type Type
* @param subtype Subtype
*/
public MimeTypeSimple(final String type, final String subtype) {
this.tpe = type;
this.sub = subtype;
}

@Override
public String type() {
return this.tpe;
}

@Override
public String subtype() {
return this.sub;
}

@Override
public Optional<String> param(String name) {
return Optional.empty();
}

@Override
public Set<String> params() {
return Collections.emptySet();
}
}
75 changes: 75 additions & 0 deletions src/test/java/wtf/g4s8/mime/MimeTypeParseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* The MIT License (MIT) Copyright (c) 2017-2021 Kirill Ch. <g4s8.public@gmail.com>
* https://github.com/g4s8/mime/LICENSE.txt
*/
package wtf.g4s8.mime;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import wtf.g4s8.mime.test.HmMimeHasSubType;
import wtf.g4s8.mime.test.HmMimeHasType;
import wtf.g4s8.oot.SequentialTests;
import wtf.g4s8.oot.SimpleTest;
import wtf.g4s8.oot.TestCase;

/**
* Test case for {@link MimeType}.
*
* @since 2.1
*/
final class MimeTypeParseTest extends TestCase.Wrap {

MimeTypeParseTest() {
super(
new SequentialTests(
new SimpleTest<>(
"parse multiple types",
MimeType.parse("text/html, application/xhtml+xml, application/xml, */*"),
matchers("application/xhtml+xml", "application/xml", "text/html", "*/*")
),
new SimpleTest<>(
"parse and sort by qualifier",
MimeType.parse("text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8"),
matchers("application/xhtml+xml", "text/html", "application/xml", "*/*")
),
new SimpleTest<>(
"parse and sort repeated",
MimeType.parse(
"text/html;q=0.6, application/xml;q=0.9, image/bmp;q=0.3,image/bmp;q=0.5, text/html, multipart/mixed, text/json;q=0.4"
),
matchers(
"multipart/mixed", "text/html", "application/xml", "image/bmp", "text/json"
)
),
new SimpleTest<>(
"parse docker client header",
MimeType.parse(
"application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.v2+json,application/vnd.docker.distribution.manifest.v1+json,application/vnd.docker.distribution.manifest.list.v2+json"
),
matchers(
"application/vnd.docker.distribution.manifest.list.v2+json",
"application/vnd.docker.distribution.manifest.v1+json",
"application/vnd.docker.distribution.manifest.v2+json",
"application/vnd.oci.image.manifest.v1+json"
)
)
)
);
}

/**
* Short method for matcher.
* @oaram expect Expected mime types
* @return Matcher
*/
private static Matcher<Iterable<? extends MimeType>> matchers(final String... expect) {
return Matchers.contains(
Stream.of(expect)
.map(item -> item.split("/"))
.map(split -> Matchers.allOf(new HmMimeHasType(split[0]), new HmMimeHasSubType(split[1])))
.collect(Collectors.toList())
);
}
}
33 changes: 0 additions & 33 deletions src/test/java/wtf/g4s8/mime/MimeTypeTest.java

This file was deleted.

5 changes: 4 additions & 1 deletion src/test/java/wtf/g4s8/mime/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ public final class Test extends TestCase.Wrap {
*/
private Test() {
super(
new SequentialTests(new MimeTypeOfTest())
new SequentialTests(
new MimeTypeOfTest(),
new MimeTypeParseTest()
)
);
}

Expand Down