/** * Returns the best supported encoding for a given client. * * @param client The client preferences to use. * @return The best supported encoding for the given call. */ public Encoding getBestEncoding(ClientInfo client) { Encoding bestEncoding = null; Encoding currentEncoding = null; Preference<Encoding> currentPref = null; float bestScore = 0F; for (Iterator<Encoding> iter = getSupportedEncodings().iterator(); iter.hasNext(); ) { currentEncoding = iter.next(); for (Iterator<Preference<Encoding>> iter2 = client.getAcceptedEncodings().iterator(); iter2.hasNext(); ) { currentPref = iter2.next(); if (currentPref.getMetadata().equals(Encoding.ALL) || currentPref.getMetadata().equals(currentEncoding)) { // A match was found, compute its score if (currentPref.getQuality() > bestScore) { bestScore = currentPref.getQuality(); bestEncoding = currentEncoding; } } } } return bestEncoding; }
@Override public PreferenceWriter append(Preference<?> pref) { append(pref.getMetadata().getName()); if (pref.getQuality() < 1F) { append(";q="); appendQuality(pref.getQuality()); } if (pref.getParameters() != null) { Parameter param; for (Iterator<Parameter> iter = pref.getParameters().iterator(); iter.hasNext(); ) { param = iter.next(); if (param.getName() != null) { append(';').append(param.getName()); if ((param.getValue() != null) && (param.getValue().length() > 0)) { append('=').append(param.getValue()); } } } } return this; }
/** * Returns an enriched list of preferences. Contains the user preferences, implied user parent * preferences (quality between 0.005 and 0.006), default preference (quality of 0.003), default * parent preference (quality of 0.002), all preference (quality of 0.001).<br> * <br> * This necessary to compensate the misconfiguration of many browsers which don't expose all the * metadata actually understood by end users. * * @param <T> * @param userPreferences The user preferences to enrich. * @param defaultValue The default value. * @param allValue The ALL value. * @return The enriched user preferences. */ @SuppressWarnings("unchecked") protected <T extends Metadata> List<Preference<T>> getEnrichedPreferences( List<Preference<T>> userPreferences, T defaultValue, T allValue) { List<Preference<T>> result = new ArrayList<Preference<T>>(); // 0) List all undesired metadata List<T> undesired = null; for (Preference<T> pref : userPreferences) { if (pref.getQuality() == 0) { if (undesired == null) { undesired = new ArrayList<T>(); } undesired.add(pref.getMetadata()); } } // 1) Add the user preferences result.addAll(userPreferences); // 2) Add the user parent preferences T parent; for (int i = 0; i < result.size(); i++) { Preference<T> userPref = result.get(i); parent = (T) userPref.getMetadata().getParent(); // Add the parent, if it is not proscribed. if ((parent != null)) { if (canAdd(parent, undesired)) { result.add(new Preference<T>(parent, 0.005f + (0.001f * userPref.getQuality()))); } } } // 3) Add the default preference if (defaultValue != null && canAdd(defaultValue, undesired)) { Preference<T> defaultPref = new Preference<T>(defaultValue, 0.003f); result.add(defaultPref); T defaultParent = (T) defaultValue.getParent(); if (defaultParent != null && canAdd(defaultParent, undesired)) { result.add(new Preference<T>(defaultParent, 0.002f)); } } // 5) Add "all" preference for (int i = result.size() - 1; i >= 0; i--) { // Remove any existing preference if (result.get(i).getMetadata().equals(allValue)) { result.remove(i); } } result.add(new Preference<T>(allValue, 0.001f)); // 6) Return the enriched preferences return result; }
/** * Scores a list of metadata relatively to enriched client preferences. * * @param metadataList The list of metadata to score. * @return The score. */ private <T extends Metadata> float scoreMetadata( List<T> metadataList, List<Preference<T>> prefs) { float result = -1.0F; float current; if ((metadataList != null) && !metadataList.isEmpty()) { for (Preference<T> pref : prefs) { for (T metadata : metadataList) { if (pref.getMetadata().includes(metadata)) { current = pref.getQuality(); } else { current = -1.0F; } if (current > result) { result = current; } } } } else { result = 0.0F; } return result; }
/** * 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)); }