001/*
002 *   Copyright 2020 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.auth;
017
018import java.util.*;
019
020/**
021 * Internal class, managing a collection of {@link AuthMethod}s.
022 * <p>
023 * This holds a collection of AuthMethod instances, in order of preference, and
024 * allow for simple selection of an appropriate AuthMethod for a particular REST endpoint.
025 */
026public class AuthCollection {
027    private SortedSet<AuthMethod> authList;
028
029    /**
030     * Create a new AuthCollection with an empty set of AuthMethods.
031     */
032    public AuthCollection() {
033        this.authList = new TreeSet<>();
034    }
035
036    public AuthCollection(AuthMethod... authMethods) {
037        this();
038        for (AuthMethod method : authMethods) {
039            add(method);
040        }
041    }
042
043    public AuthCollection(SortedSet<AuthMethod> authMethods) {
044        this.authList = authMethods;
045    }
046
047    /**
048     * Add a new {@link AuthMethod} to the set managed by this AuthCollection
049     *
050     * @param auth AuthMethod method to be added to this collection
051     */
052    public void add(AuthMethod auth) {
053        this.authList.add(auth);
054    }
055
056    /**
057     * Obtain an AuthMethod of type T, if one is contained in this collection.
058     *
059     * @param type The type of AuthMethod to be located
060     * @param <T>  The type of AuthMethod which will be returned
061     *
062     * @return An AuthMethod subclass matching type
063     *
064     * @throws VonageUnacceptableAuthException if no matching AuthMethod is found.
065     */
066    public <T extends AuthMethod> T getAuth(Class<T> type) throws VonageUnacceptableAuthException {
067        for (AuthMethod availableAuthMethod : this.authList) {
068            if (type.isInstance(availableAuthMethod)) {
069                return (T) availableAuthMethod;
070            }
071        }
072        throw new VonageUnacceptableAuthException(this.authList, new HashSet<>(Arrays.asList(new Class[]{type})));
073    }
074
075    /**
076     * Obtain an {@link AuthMethod} instance for a set of acceptable AuthMethod classes.
077     *
078     * @param acceptableAuthMethodClasses A Set of AuthMethod classes which are suitable for the target REST endpoint.
079     *
080     * @return the preferred AuthMethod from the provided set of acceptable AuthMethod classes
081     *
082     * @throws VonageUnacceptableAuthException if no appropriate AuthMethod is held by this AuthCollection
083     */
084    public AuthMethod getAcceptableAuthMethod(Set<Class> acceptableAuthMethodClasses) throws VonageUnacceptableAuthException {
085        for (AuthMethod availableAuthMethod : this.authList) {
086            if (acceptableAuthMethodClasses.contains(availableAuthMethod.getClass())) {
087                return availableAuthMethod;
088            }
089        }
090        throw new VonageUnacceptableAuthException(this.authList, acceptableAuthMethodClasses);
091    }
092}