/*
 * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//  - rbarkhouse - 24 February 2012 - 2.3.3 - Initial implementation
package org.eclipse.persistence.internal.jaxb;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.Callable;

import jakarta.xml.bind.ValidationEventHandler;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.IDResolver;
import org.xml.sax.SAXException;

/**
 * INTERNAL:
 * <p>
 * This class provides an implementation of IDResolver that wraps
 * an IDResolver from the Sun JAXB Implementation.
 * </p>
 */
public class IDResolverWrapper extends IDResolver {

    private final static String BIND_METHOD_NAME = "bind";
    private final static String END_DOCUMENT_METHOD_NAME = "endDocument";
    private final static String RESOLVE_METHOD_NAME = "resolve";
    private final static String START_DOCUMENT_METHOD_NAME = "startDocument";

    private final static Class[] BIND_PARAMS = new Class[] { CoreClassConstants.STRING, CoreClassConstants.OBJECT };
    private final static Class[] RESOLVE_PARAMS = new Class[] { CoreClassConstants.STRING, CoreClassConstants.CLASS };
    private final static Class[] START_DOCUMENT_PARAMS = new Class[] { ValidationEventHandler.class };

    private Object resolver;
    private Method bindMethod, endDocumentMethod, resolveMethod, startDocumentMethod;

    public IDResolverWrapper(Object sunResolver) {
        this.resolver = sunResolver;
        Class<? extends Object> resolverClass = sunResolver.getClass();

        try {
            this.bindMethod = PrivilegedAccessHelper.getMethod(resolverClass, BIND_METHOD_NAME, BIND_PARAMS, false);
        } catch (Exception ex) {
            throw XMLMarshalException.errorProcessingIDResolver(BIND_METHOD_NAME, sunResolver, ex);
        }
        try {
            this.endDocumentMethod = PrivilegedAccessHelper.getMethod(resolverClass, END_DOCUMENT_METHOD_NAME, new Class[] {}, false);
        } catch (Exception ex) {
            throw XMLMarshalException.errorProcessingIDResolver(END_DOCUMENT_METHOD_NAME, sunResolver, ex);
        }
        try {
            this.resolveMethod = PrivilegedAccessHelper.getMethod(resolverClass, RESOLVE_METHOD_NAME, RESOLVE_PARAMS, false);
        } catch (Exception ex) {
            throw XMLMarshalException.errorProcessingIDResolver(RESOLVE_METHOD_NAME, sunResolver, ex);
        }
        try {
            this.startDocumentMethod = PrivilegedAccessHelper.getMethod(resolverClass, START_DOCUMENT_METHOD_NAME, START_DOCUMENT_PARAMS, false);
        } catch (Exception ex) {
            throw XMLMarshalException.errorProcessingIDResolver(START_DOCUMENT_METHOD_NAME, sunResolver, ex);
        }
    }

    @Override
    public void bind(Object id, Object obj) throws SAXException {
        try {
            Object[] params = new Object[] { id.toString(), obj };
            PrivilegedAccessHelper.invokeMethod(this.bindMethod, this.resolver, params);
        } catch (Exception ex) {
            throw XMLMarshalException.errorInvokingIDResolver(BIND_METHOD_NAME, this.resolver, ex);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        try {
            PrivilegedAccessHelper.invokeMethod(this.endDocumentMethod, this.resolver, new Object[] {});
        } catch (Exception ex) {
            throw XMLMarshalException.errorInvokingIDResolver(END_DOCUMENT_METHOD_NAME, this.resolver, ex);
        }
    }

    @Override
    public void startDocument(ValidationEventHandler eventHandler) throws SAXException {
        try {
            Object[] params = new Object[] { eventHandler };
            PrivilegedAccessHelper.invokeMethod(this.startDocumentMethod, this.resolver, params);
        } catch (Exception ex) {
            throw XMLMarshalException.errorInvokingIDResolver(START_DOCUMENT_METHOD_NAME, this.resolver, ex);
        }
    }

    @Override
    public Callable<?> resolve(Object id, Class targetType) throws SAXException {
        try {
            Object[] params = new Object[] { id.toString(), targetType };
            return PrivilegedAccessHelper.invokeMethod(this.resolveMethod, this.resolver, params);
        } catch (Exception ex) {
            throw XMLMarshalException.errorInvokingIDResolver(RESOLVE_METHOD_NAME, this.resolver, ex);
        }
    }

    @Override
    public Callable<?> resolve(Map<String, Object> id, Class type) throws SAXException {
        // If the user is still using a Sun IDResolver, then they must only have one XML ID,
        // as only EclipseLink supports multiple IDs through XmlKey.  So if this method is called,
        // throw an exception informing the user.
        throw XMLMarshalException.wrappedIDResolverWithMultiID(id.toString(), this.resolver);
    }

    @Override
    public void bind(Map<String, Object> id, Object obj) throws SAXException {
        // If the user is still using a Sun IDResolver, then they must only have one XML ID,
        // as only EclipseLink supports multiple IDs through XmlKey.  So if this method is called,
        // throw an exception informing the user.
        throw XMLMarshalException.wrappedIDResolverWithMultiID(id.toString(), this.resolver);
    }

    public Object getResolver() {
        return this.resolver;
    }

}
