/*
 * 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 {@link ServiceRegistryDao} that reads services definition from the OSF at the initialization time
 * of Spring Application Context.
 *
 * Note: Similar to the OSF and its services (e.g. preprints, registries, etc.), OSF developer apps loaded from the OSF
 *       database are treated as {@link RegisteredService}. CAS determines which service it is by "regex" checking the
 *       "service" query parameter in the login URL against the {@link RegisteredService#getServiceId()}. If a service
 *       matches two or more {@code serviceId}, the one with the highest {@link RegisteredService#getEvaluationOrder()}
 *       will be matched. The order is a non-negative integer, {@code 0} is the highest and the order decreases as the
 *       value grows larger.
 *
 *       {@link OpenScienceFrameworkApiOauth2Application#getCallbackUrl()} is entered by the owner of the developer app
 *       via OSF and it is used here in CAS to set the {@code serviceId}. Thus we must set the evaluation order to the
 *       lowest so that it does not take over other services. Here are a list of evaluation orders:
 *
 *       1. 1000: branded preprints, CAS oauth callback authorization service
 *       2. 1500: OSF preprints, OSF registries
 *       3. 2000: OSF, CAS
 *       4. 3000: OSF developer apps
 *
 * @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;

    private static final int EVALUATION_ORDER = 3000;

    /** 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.setEvaluationOrder(EVALUATION_ORDER);
            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);
    }
}

@@ -790,16 +790,17 @@
 cation;%0A
+%0A
 import o
@@ -1017,32 +1017,33 @@
 isteredService;%0A
+%0A
 import org.slf4j
@@ -1083,16 +1083,17 @@
 actory;%0A
+%0A
 import j
@@ -2623,11 +2623,12 @@
 nce 
-4.1
+19.3
 .0%0A 
@@ -3862,16 +3862,90 @@
 load() %7B
+%0A%0A        // Load all OSF developer apps from the OSF database via OSF DAO
 %0A       
@@ -4011,16 +4011,32 @@
 Services
+%0A               
  = openS
@@ -4076,24 +4076,65 @@
 cations();%0A%0A
+        // Init attribute release policy%0A
         fina
@@ -4243,91 +4243,8 @@
 ();%0A
-        final Map%3CLong, RegisteredService%3E serviceMap = new ConcurrentHashMap%3C%3E();%0A
     
@@ -4322,35 +4322,8 @@
     
-/**%0A         * e.g. global 
 attr
@@ -4331,29 +4331,26 @@
 bute
- r
+R
 elease
-%0A         * a
+Policy.setA
 llow
@@ -4365,37 +4365,9 @@
 utes
-.add(%22username%22);%0A         * 
+(
 allo
@@ -4383,35 +4383,20 @@
 utes
-.add(%22givenName%22
 );%0A
+%0A
         
  * a
@@ -4395,129 +4395,177 @@
     
- * allowedAttributes.add(%22familyName%22);%0A         */%0A        attributeReleasePolicy.setAllowedAttributes(allowedAttributes
+// Create the registered service for each developer app and put them into  a service map%0A        final Map%3CLong, RegisteredService%3E serviceMap = new ConcurrentHashMap%3C%3E(
 );%0A 
@@ -5391,16 +5391,78 @@
        %7D
+%0A%0A        // Set the service map and return a list of services
 %0A       

Fix the "since" tag, update style and add comments