/** * Copyright 2005-2014 Restlet * * The contents of this file are subject to the terms of one of the following * open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can * select the license that you prefer but you may not use this file except in * compliance with one of these Licenses. * * You can obtain a copy of the Apache 2.0 license at * http://www.opensource.org/licenses/apache-2.0 * * You can obtain a copy of the EPL 1.0 license at * http://www.opensource.org/licenses/eclipse-1.0 * * See the Licenses for the specific language governing permissions and * limitations under the Licenses. * * Alternatively, you can obtain a royalty free commercial license with less * limitations, transferable or non-transferable, directly at * http://restlet.com/products/restlet-framework * * Restlet is a registered trademark of Restlet S.A.S. */ package org.restlet.ext.jaxrs.internal.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.SortedMap; import java.util.TreeMap; import org.restlet.data.Language; import org.restlet.data.MediaType; import org.restlet.data.Metadata; import org.restlet.data.Preference; /** * SortedMetadata contains given Metadata, sorted by it's quality, Metadata with * the highest quality first. * * @author Stephan Koops * @param <T> * the Metadata type the instance contains. */ public class SortedMetadata<T extends Metadata> implements Iterable<T> { @SuppressWarnings("hiding") private class IteratorIterator<T extends Metadata> implements Iterator<T> { private Iterator<T> iter; private final Iterator<Iterable<T>> iterIter; IteratorIterator(Iterator<Iterable<T>> iterIter) { this.iterIter = iterIter; } public boolean hasNext() { if ((this.iter != null) && this.iter.hasNext()) { return true; } while (this.iterIter.hasNext()) { final Iterable<T> iterable = this.iterIter.next(); if (iterable != null) { this.iter = iterable.iterator(); if (this.iter.hasNext()) { return true; } } } return false; } public T next() { if (this.hasNext()) { return this.iter.next(); } throw new NoSuchElementException(); } /** * * @see java.util.Iterator#remove() */ public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } } /** * @param respMediaType * @return the media type as singleton of SortedMetadata */ public static SortedMetadata<MediaType> get(MediaType respMediaType) { return new SortedMetadata<MediaType>( Collections.singleton(new Preference<MediaType>(respMediaType))); } /** * Returns an empty SortedMetadata * * @return an empty SortedMetadata */ public static SortedMetadata<MediaType> getEmptyMediaTypes() { return new SortedMetadata<MediaType>( new ArrayList<Collection<MediaType>>()); } /** * Creates a new {@link SortedMetadata} for {@link MediaType}s. * * @param preferences * @return the given languages as SortedMetadata */ public static SortedMetadata<Language> getForLanguages( Collection<Preference<Language>> preferences) { return new SortedMetadata<Language>(preferences); } /** * Creates a new {@link SortedMetadata} for {@link MediaType}s. If the given * Collection is empty, {@link MediaType#ALL} is returned. * * @param preferences * @return the given media type as SortedMetadata */ public static SortedMetadata<MediaType> getForMediaTypes( Collection<Preference<MediaType>> preferences) { if (preferences.isEmpty()) { return new SortedMetadata<MediaType>( Collections .singletonList((Collection<MediaType>) Collections .singletonList(MediaType.ALL))); } return new SortedMetadata<MediaType>(preferences); } /** * Creates a SortedMetadata collection with exactly the {@link MediaType} * '*<!---->/*'' * * @return '*<!---->/*'' as SortedMediaType * @see MediaType#ALL */ public static SortedMetadata<MediaType> getMediaTypeAll() { return new SortedMetadata<MediaType>(Collections.singletonList(Util .createColl(MediaType.ALL))); } /** * * @param mediaType * @return the media type as singleton as SortedMetadata * @see Collections#singleton(Object) */ public static SortedMetadata<MediaType> singleton(MediaType mediaType) { return new SortedMetadata<MediaType>(Collections.singletonList(Util .createColl(mediaType))); } private final List<Collection<T>> metadatas; /** * Creates a new SortedMetadata from the given Metadata. * * @param preferences */ @SuppressWarnings({ "unchecked", "rawtypes" }) private SortedMetadata(Collection<Preference<T>> preferences) { SortedMap<Float, Collection<T>> map = new TreeMap<Float, Collection<T>>( Collections.reverseOrder()); for (Preference<T> preference : preferences) { Float quality = preference.getQuality(); Collection<T> metadatas = map.get(quality); if (metadatas == null) { metadatas = new ArrayList<T>(2); map.put(quality, metadatas); } metadatas.add(preference.getMetadata()); } Collection<Collection<T>> values = map.values(); this.metadatas = Collections.unmodifiableList(new ArrayList(values)); } /** * Creates a new SortedMetadata from the sorted Metadata. * * @param metadatas */ private SortedMetadata(List<Collection<T>> metadatas) { this.metadatas = metadatas; } /** * Checks, if this SortedMetadata is empty * * @return true, if this sorted metadata is empty, or false if not. * @see Collection#isEmpty() */ public boolean isEmpty() { return this.metadatas.isEmpty(); } /** * Iterates over all the sorted Metadata. * * @see java.lang.Iterable#iterator() */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Iterator<T> iterator() { return new IteratorIterator(this.metadatas.iterator()); } /** * Returns the list of collections as {@link Iterable} of {@link Iterable}s. * * @return the list of collections as {@link Iterable} of {@link Iterable}s. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Iterable<Iterable<T>> listOfColls() { return (Iterable) this.metadatas; } @Override public String toString() { return this.metadatas.toString(); } }