/*
 * Copyright (c) 2015. Center for Open Science
 *
 * Licensed 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 io.cos.cas.services;

import io.cos.cas.adaptors.postgres.daos.OpenScienceFrameworkDaoImpl;
import io.cos.cas.adaptors.postgres.models.OpenScienceFrameworkApiOauth2Application;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.services.ReturnAllowedAttributeReleasePolicy;
import org.jasig.cas.services.ServiceRegistryDao;
import org.jasig.cas.support.oauth.services.OAuthRegisteredService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Implementation of <code>ServiceRegistryDao</code> that reads services definition from the
 * Open Science Framework at the Spring Application Context initialization time.
 *
 * @author Michael Haselton
 * @author Longze Chen
 * @since 4.1.0
 */
public class OpenScienceFrameworkServiceRegistryDao implements ServiceRegistryDao {

    private static final Logger LOGGER = LoggerFactory.getLogger(OpenScienceFrameworkServiceRegistryDao.class);

    private static final int HEX_RADIX = 16;

    /** Map of service ID to registered service. */
    private Map<Long, RegisteredService> serviceMap = new ConcurrentHashMap<>();

    /** The Open Science Framework Data Access Model. */
    private OpenScienceFrameworkDaoImpl openScienceFrameworkDao;

    /**
     * Instantiates a new Open Science Framework service registry dao.
     *
     * @param openScienceFrameworkDao the open science framework data access object
     */
    public OpenScienceFrameworkServiceRegistryDao(final OpenScienceFrameworkDaoImpl openScienceFrameworkDao) {
        this.openScienceFrameworkDao = openScienceFrameworkDao;
    }

    @Override
    public final RegisteredService save(final RegisteredService service) {
        return null;
    }

    @Override
    public final synchronized boolean delete(final RegisteredService service) {
        return false;
    }

    @Override
    public final synchronized List<RegisteredService> load() {
        final List<OpenScienceFrameworkApiOauth2Application> oAuthServices = openScienceFrameworkDao.findOauthApplications();

        final ReturnAllowedAttributeReleasePolicy attributeReleasePolicy = new ReturnAllowedAttributeReleasePolicy();
        final Map<Long, RegisteredService> serviceMap = new ConcurrentHashMap<>();
        final ArrayList<String> allowedAttributes = new ArrayList<>();
        /**
         * e.g. global attribute release
         * allowedAttributes.add("username");
         * allowedAttributes.add("givenName");
         * allowedAttributes.add("familyName");
         */
        attributeReleasePolicy.setAllowedAttributes(allowedAttributes);
        for (final OpenScienceFrameworkApiOauth2Application oAuthService : oAuthServices) {
            final OAuthRegisteredService service = new OAuthRegisteredService();
            service.setId(new BigInteger(oAuthService.getId(), HEX_RADIX).longValue());
            service.setName(oAuthService.getName());
            service.setDescription(oAuthService.getDescription());
            service.setServiceId(oAuthService.getCallbackUrl());
            service.setBypassApprovalPrompt(Boolean.FALSE);
            service.setClientId(oAuthService.getClientId());
            service.setClientSecret(oAuthService.getClientSecret());
            service.setAttributeReleasePolicy(attributeReleasePolicy);
            serviceMap.put(service.getId(), service);
        }
        this.serviceMap = serviceMap;
        return new ArrayList<>(this.serviceMap.values());
    }

    @Override
    public final RegisteredService findServiceById(final long id) {
        return serviceMap.get(id);
    }
}

@@ -1260,14 +1260,15 @@
  of 
-%3Ccode%3E
+%7B@link 
 Serv
@@ -1285,15 +1285,9 @@
 yDao
-%3C/code%3E
+%7D
  tha
@@ -1326,89 +1326,1237 @@
  the
-%0A * Open Science Framework at the Spring Application Context initialization time.
+ OSF at the initialization time%0A * of Spring Application Context.%0A *%0A * Note: Similar to the OSF and its services (e.g. preprints, registries, etc.), OSF developer apps loaded from the OSF%0A *       database are treated as %7B@link RegisteredService%7D. CAS determines which service it is by %22regex%22 checking the%0A *       %22service%22 query parameter in the login URL against the %7B@link RegisteredService#getServiceId()%7D. If a service%0A *       matches two or more %7B@code serviceId%7D, the one with the highest %7B@link RegisteredService#getEvaluationOrder()%7D%0A *       will be matched. The order is a non-negative integer, %7B@code 0%7D is the highest and the order decreases as the%0A *       value grows larger.%0A *%0A *       %7B@link OpenScienceFrameworkApiOauth2Application#getCallbackUrl()%7D is entered by the owner of the developer app%0A *       via OSF and it is used here in CAS to set the %7B@code serviceId%7D. Thus we must set the evaluation order to the%0A *       lowest so that it does not take over other services. Here are a list of evaluation orders:%0A *%0A *       1. 1000: branded preprints, CAS oauth callback authorization service%0A *       2. 1500: OSF preprints, OSF registries%0A *       3. 2000: OSF, CAS%0A *       4. 3000: OSF developer apps
 %0A *%0A
@@ -2820,24 +2820,24 @@
 ao.class);%0A%0A
-
     private 
@@ -2870,16 +2870,71 @@
  = 16;%0A%0A
+    private static final int EVALUATION_ORDER = 3000;%0A%0A
     /** 
@@ -4978,24 +4978,82 @@
 backUrl());%0A
+            service.setEvaluationOrder(EVALUATION_ORDER);%0A
             

Set evaluation order for OAuth apps to the lowest