All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wink.common.internal.http.Accept Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *  
 *******************************************************************************/

package org.apache.wink.common.internal.http;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.RuntimeDelegate;
import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;

import org.apache.wink.common.internal.utils.MediaTypeUtils;

/**
 * Represents a HTTP Accept header (see 14.1 of RFC 2616).
 */
public class Accept {

    private static final HeaderDelegate delegate =
                                                             RuntimeDelegate
                                                                 .getInstance()
                                                                 .createHeaderDelegate(Accept.class);

    private List                     mediaTypes;
    private List               valuedMediaTypes;
    private List               sortedValuedMediaTypes;
    private List                     sortedMediaTypes;

    public Accept(List mediaTypes) {
        this.mediaTypes = mediaTypes;
        if (mediaTypes.isEmpty()) {
            throw new IllegalArgumentException();
        }
        this.valuedMediaTypes = new LinkedList();
        for (MediaType mt : mediaTypes) {
            this.valuedMediaTypes.add(new ValuedMediaType(mt));
        }
        this.sortedValuedMediaTypes = sort(new LinkedList(this.valuedMediaTypes));
        sortedMediaTypes = new LinkedList();
        for (ValuedMediaType vmt : sortedValuedMediaTypes) {
            sortedMediaTypes.add(vmt.getMediaType());
        }
    }

    private List sort(List types) {
        // sort the accept media types.
        // use the reverseOrder() method because sort()
        // will sort in ascending order and we want descending order
        Collections.sort(types, Collections.reverseOrder());
        return types;
    }

    /**
     * Get an unmodifiable list of the valued media types in the accept header
     * 
     * @return an unmodifiable list of the valued media types
     */
    public List getValuedMediaTypes() {
        return Collections.unmodifiableList(valuedMediaTypes);
    }

    /**
     * Get a sorted unmodifiable list of the valued media types in the accept
     * header
     * 
     * @return a sorted unmodifiable list of the valued media types
     */
    public List getSortedValuedMediaTypes() {
        return Collections.unmodifiableList(sortedValuedMediaTypes);
    }

    /**
     * Get an unmodifiable list of the media types in the accept header
     * 
     * @return an unmodifiable list of the accept media types
     */
    public List getMediaTypes() {
        return mediaTypes;
    }

    /**
     * Get a sorted unmodifiable list of the valued media types in the accept
     * header
     * 
     * @return a sorted unmodifiable list of the valued media types
     */
    public List getSortedMediaTypes() {
        return Collections.unmodifiableList(sortedMediaTypes);
    }

    /**
     * Is media type acceptable by this Accept header
     * 
     * @param mt a media type to check for acceptance
     * @return true if acceptable, false otherwise
     */
    public boolean isAcceptable(MediaType mt) {
        boolean accpetable = false;
        for (ValuedMediaType vmt : valuedMediaTypes) {
            if (vmt.isCompatible(mt)) {
                if (vmt.getQ() == 0) {
                    return false;
                }
                accpetable = true;
            }
        }
        return accpetable;
    }

    /**
     * Creates a new instance of Accept by parsing the supplied string.
     * 
     * @param value the accept string
     * @return the newly created Accept
     * @throws IllegalArgumentException if the supplied string cannot be parsed
     */
    public static Accept valueOf(String value) throws IllegalArgumentException {
        return delegate.fromString(value);
    }

    /**
     * Convert the accept to a string suitable for use as the value of the
     * corresponding HTTP header.
     * 
     * @return a stringified accept
     */
    @Override
    public String toString() {
        return delegate.toString(this);
    }

    /**
     * Represents a media type along with its q value.
     */
    public static class ValuedMediaType implements Comparable {
        private double    q;
        private MediaType mediaType;

        public ValuedMediaType(MediaType mediaType) {
            double q = 1;
            String qStr = mediaType.getParameters().get("q"); //$NON-NLS-1$
            if (qStr != null) {
                q = Double.parseDouble(qStr);
            }
            init(mediaType, q);
        }

        public ValuedMediaType(MediaType mediaType, double q) {
            init(mediaType, q);
        }

        private void init(MediaType mediaType, double q) {
            if (mediaType == null) {
                throw new NullPointerException("mediaType"); //$NON-NLS-1$
            }
            if (q < 0 || q > 1) {
                throw new IllegalArgumentException(String.valueOf(q));
            }
            this.mediaType = mediaType;
            // strip digits after the first 3
            this.q = ((double)((int)(q * 1000))) / 1000;
            // if the result q is different than the initial q, then create a
            // new MediaType
            // with the stripped q value
            if (this.q != q) {
                Map parameters = new LinkedHashMap();
                parameters.putAll(mediaType.getParameters());
                parameters.put("q", Double.toString(this.q)); //$NON-NLS-1$
                this.mediaType =
                    new MediaType(mediaType.getType(), mediaType.getSubtype(), parameters);
            }
        }

        public double getQ() {
            return q;
        }

        public MediaType getMediaType() {
            return mediaType;
        }

        public boolean isCompatible(MediaType other) {
            return mediaType.isCompatible(other);
        }

        public String toString() {
            return mediaType.toString();
        }

        public int compareTo(ValuedMediaType o) {
            int ret = Double.compare(q, o.q);
            if (ret != 0) {
                return ret;
            }
            return MediaTypeUtils.compareTo(mediaType, o.mediaType);
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy