/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you 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 the following location:
 *
 *   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.web.flow;

import com.google.gson.Gson;

import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * Open Science Framework Login Handler.
 *
 * @author Longze Chen
 * @since 4.1.5
 */
public class OpenScienceFrameworkLoginHandler {

    /**
     * Open Science Framework Login Context.
     *
     * @author Longze chen
     * @since  4.1.5
     */
    public static final class OpenScienceFrameworkLoginContext {

        /** The service URL in the context. */
        private String serviceUrl;

        /** The simple name of the authentication exception that just happened. */
        private String handleErrorName;

        /** The flag for institution login instead of normal OSF login. */
        private boolean institutionLogin;

        /** The flag for redirect to ORCiD login instead of normal OSF login. */
        private boolean orcidRedirect;

        /**
         * Construct an instance of `OpenScienceFrameworkLoginContext` with the given settings.
         *
         * @param serviceUrl the service URL
         * @param institutionLogin the flag for institution login
         */
        private OpenScienceFrameworkLoginContext(final String serviceUrl, final boolean institutionLogin) {
            this.serviceUrl = serviceUrl;
            this.handleErrorName = null;
            this.institutionLogin = institutionLogin;
        }

        public String getServiceUrl() {
            return serviceUrl;
        }

        public void setServiceUrl(final String serviceUrl) {
            this.serviceUrl = serviceUrl;
        }

        public String getHandleErrorName() {
            return handleErrorName;
        }

        public void setHandleErrorName(final String handleErrorName) {
            this.handleErrorName =handleErrorName;
        }

        public boolean getInstitutionLogin() {
            return institutionLogin;
        }

        public void setInstitutionLogin(final Boolean institutionLogin) {
            this.institutionLogin = institutionLogin;
        }

        public boolean isOrcidRedirect() {
            return orcidRedirect;
        }

        public void setOrcidRedirect(final boolean orcidRedirect) {
            this.orcidRedirect = orcidRedirect;
        }

        /**
         * Check if the service URL exists.
         *
         * @return true if service url exists, false otherwise
         */
        public boolean isServiceUrl() {
            return serviceUrl != null;
        }

        /**
         * Check if it is institution login.
         *
         * @return true if institution login, false otherwise
         */
        public boolean isInstitutionLogin() {
            return institutionLogin;
        }

        /**
         * Convert the class instance to a JSON string, which will be passed to the flow context.
         *
         * @return JSON string
         */
        public String toJson() {
            final Gson gson = new Gson();
            return gson.toJson(this);
        }

        /**
         * Convert the JSON string to a class instance.
         *
         * @param jsonString a JSON string previously generated by the method .toJson()
         * @return an reconstructed instance of OpenScienceFrameworkLoginContext
         */
        public static OpenScienceFrameworkLoginContext fromJson(final String jsonString) {
            final Gson gson = new Gson();
            return gson.fromJson(jsonString, OpenScienceFrameworkLoginContext.class);
        }
    }

    /**
     * Prepare for the login request and make decisions for next steps.
     *
     * @param context the request context
     * @return the next event to go to
     */
    public Event beforeLogin(final RequestContext context) {

        final OpenScienceFrameworkLoginContext osfLoginContext;
        final String serviceUrl = getEncodedServiceUrl(context);
        final boolean institutionLogin = isInstitutionLogin(context);
        final boolean orcidRedirect = isOrcidRedirect(context);

        String jsonLoginContext = (String) context.getFlowScope().get("jsonLoginContext");
        if (jsonLoginContext == null) {
            // Create a new login context with service URL and institution login flag
            osfLoginContext = new OpenScienceFrameworkLoginContext(serviceUrl, institutionLogin);
            // Only allow ORCiD login redirect from a brand new login flow
            osfLoginContext.setOrcidRedirect(orcidRedirect);
        } else {
            // If the login context already exists, update the service URL and the institution login flag while keeping
            // the errors and disabling ORCiD login redirect
            osfLoginContext = OpenScienceFrameworkLoginContext.fromJson(jsonLoginContext);
            osfLoginContext.setServiceUrl(serviceUrl);
            osfLoginContext.setInstitutionLogin(institutionLogin);
            osfLoginContext.setOrcidRedirect(false);
        }
        jsonLoginContext = osfLoginContext.toJson();
        context.getFlowScope().put("jsonLoginContext", jsonLoginContext);

        if (osfLoginContext.isInstitutionLogin()) {
            return new Event(this, "institutionLogin");
        } else if (osfLoginContext.isOrcidRedirect()) {
            return new Event(this, "orcidLoginRedirect");
        } else {
            return new Event(this, "osfDefaultLogin");
        }
    }

    /**
     * Check if the request is institution login.
     *
     * @param context the request context
     * @return true if `campaign=institution` is present in the request parameters
     */
    private boolean isInstitutionLogin(final RequestContext context) {
        final String campaign = context.getRequestParameters().get("campaign");
        return "institution".equals(campaign);
    }

    /**
     * Check if the request is ORCiD login redirect.
     *
     * @param context the request context
     * @return true if `redirectOrcid=true` is present in the request parameters
     */
    private boolean isOrcidRedirect(final RequestContext context) {
        final String orcidRedirect = context.getRequestParameters().get("redirectOrcid");
        return orcidRedirect != null && "true".equals(orcidRedirect.toLowerCase());
    }

    /**
     * Obtain the service URL in the request parameters.
     *
     * The service URL from the request context is decoded (one level from what is originally in the request URL). Must
     * encode it before sending it to the page via the login context. If the service URL doesn't exist, return `null`.
     *
     * @param context the request context
     * @return the encoded service url
     * @throws AssertionError if encoding fails
     */
    private String getEncodedServiceUrl(final RequestContext context) throws AssertionError {
        final String serviceUrl = context.getRequestParameters().get("service");
        if (serviceUrl == null || serviceUrl.isEmpty()) {
            return null;
        }
        try {
            return URLEncoder.encode(serviceUrl, "UTF-8");
        } catch (final UnsupportedEncodingException e) {
            throw new AssertionError("UTF-8 is unknown");
        }
    }
}

@@ -2749,19 +2749,18 @@
 boolean 
-get
+is
 Institut
@@ -2866,17 +2866,17 @@
 n(final 
-B
+b
 oolean i
@@ -3410,244 +3410,8 @@
  %7D%0A%0A
-        /**%0A         * Check if it is institution login.%0A         *%0A         * @return true if institution login, false otherwise%0A         */%0A        public boolean isInstitutionLogin() %7B%0A            return institutionLogin;%0A        %7D%0A%0A
     

Fix setter and getter for OSFLoginContext