001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.client;
007
008import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
009import static java.util.Optional.ofNullable;
010
011import java.time.ZoneId;
012import java.time.format.DateTimeFormatter;
013import java.util.List;
014import java.util.Map;
015import java.util.Map.Entry;
016import java.util.Optional;
017import java.util.stream.Collectors;
018
019/**
020 * Helpers for constructing headers.
021 *
022 * @author bbpennel
023 */
024public class HeaderHelpers {
025
026    // Formatter for converting instants to RFC1123 timestamps in UTC
027    public static DateTimeFormatter UTC_RFC_1123_FORMATTER = RFC_1123_DATE_TIME.withZone(ZoneId.of("UTC"));
028
029    /**
030     * Format a map of values to q values into a quality value formatted header, as per:
031     *  https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
032     *
033     * For example, "md5;q=1.0, sha256,sha512;q=0.3"
034     *
035     * @param qualityMap mapping of values to their quality values.
036     * @return Formatted quality value header representation of the provided map.
037     */
038    public static String formatQualityValues(final Map<String, ? extends Object> qualityMap) {
039        // Group header values by common q values
040        final Map<Optional<Object>, List<Entry<String, ? extends Object>>> qualityToVal =
041                qualityMap.entrySet().stream()
042                .collect(Collectors.groupingBy(e -> ofNullable(e.getValue())));
043
044        // Join together all the groupings of q values to header values to produce final header
045        return qualityToVal.entrySet().stream()
046                .map(e -> {
047                    // Join together all the header values with the same q value
048                    final String joinedValues = e.getValue().stream()
049                            .map(Entry::getKey)
050                            .collect(Collectors.joining(","));
051                    // Add the q value if one was specified
052                    if (e.getKey().isPresent()) {
053                        return joinedValues + ";q=" + e.getKey().get();
054                    } else {
055                        return joinedValues;
056                    }
057                }) // join together the groupings
058                .collect(Collectors.joining(", "));
059    }
060
061    private HeaderHelpers() {
062    }
063}