package ca.uhn.fhir.context;

/*
 * #%L
 * HAPI FHIR - Core Library
 * %%
 * Copyright (C) 2014 University Health Network
 * %%
 * 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.
 * #L%
 */

import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.ProvidesResources;

/**
 * Scans a class tagged with {@code ProvidesResources} and adds any resources listed to its FhirContext's resource
 * definition list. This makes the profile generator find the classes.
 *
 * @see ca.uhn.fhir.model.api.annotation.ProvidesResources
 */
public class ProvidedResourceScanner {
    private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ModelScanner.class);
    private FhirContext myContext;

    /**
     * Constructor
     * @param theContext - context whose resource definition list is to be updated by the scanner
     */
    public ProvidedResourceScanner(FhirContext theContext) {
        myContext = theContext;
    }

    /**
     * If {@code theProvider} is tagged with the {@code ProvidesResources} annotation, this method will add every resource listed
     * by the {@code resources} method.
     * <p>
     * Notes:
     * </p>
     * <ul>
     * <li>if {@code theProvider} isn't annotated with {@code resources} nothing is done; it's expected that most RestfulServers and
     * ResourceProviders won't be annotated.</li>
     * <li>any object listed in {@code resources} that doesn't implement {@code IResource} will generate a warning in the log.</li>
     * </ul>
     *
     * @param theProvider - Normally, either a {@link ca.uhn.fhir.rest.server.RestfulServer} or a {@link ca.uhn.fhir.rest.server.IResourceProvider}
     *                    that might be annotated with {@link ca.uhn.fhir.model.api.annotation.ProvidesResources}
     */
    public void scanForProvidedResources(Object theProvider) {
        ProvidesResources annotation = theProvider.getClass().getAnnotation(ProvidesResources.class);
        if (annotation == null)
            return;
        for (Class clazz : annotation.resources()) {
            if (IResource.class.isAssignableFrom(clazz)) {
                myContext.getResourceDefinition(clazz);
            } else {
                ourLog.warn(clazz.getSimpleName() + "is not assignable from IResource");
            }
        }
    }
}
