001package ca.uhn.fhir.context; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2019 University Health Network 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import org.hl7.fhir.instance.model.api.IBaseResource; 024 025import ca.uhn.fhir.model.api.annotation.ProvidesResources; 026 027/** 028 * Scans a class tagged with {@code ProvidesResources} and adds any resources listed to its FhirContext's resource 029 * definition list. This makes the profile generator find the classes. 030 * 031 * @see ca.uhn.fhir.model.api.annotation.ProvidesResources 032 */ 033public class ProvidedResourceScanner { 034 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ProvidedResourceScanner.class); 035 private FhirContext myContext; 036 037 /** 038 * Constructor 039 * 040 * @param theContext 041 * - context whose resource definition list is to be updated by the scanner 042 */ 043 public ProvidedResourceScanner(FhirContext theContext) { 044 myContext = theContext; 045 } 046 047 /** 048 * If {@code theProvider} is tagged with the {@code ProvidesResources} annotation, this method will add every 049 * resource listed by the {@code resources} method. 050 * <p> 051 * Notes: 052 * </p> 053 * <ul> 054 * <li>if {@code theProvider} isn't annotated with {@code resources} nothing is done; it's expected that most 055 * RestfulServers and ResourceProviders won't be annotated.</li> 056 * <li>any object listed in {@code resources} that doesn't implement {@code IResource} will generate a warning in the 057 * log.</li> 058 * </ul> 059 * 060 * @param theProvider 061 * - Normally, either a {@link ca.uhn.fhir.rest.server.RestfulServer} or a 062 * {@link ca.uhn.fhir.rest.server.IResourceProvider} that might be annotated with 063 * {@link ca.uhn.fhir.model.api.annotation.ProvidesResources} 064 */ 065 @SuppressWarnings("unchecked") 066 public void scanForProvidedResources(Object theProvider) { 067 ProvidesResources annotation = theProvider.getClass().getAnnotation(ProvidesResources.class); 068 if (annotation == null) 069 return; 070 for (Class<?> clazz : annotation.resources()) { 071 if (IBaseResource.class.isAssignableFrom(clazz)) { 072 myContext.getResourceDefinition((Class<? extends IBaseResource>) clazz); 073 } else { 074 ourLog.warn(clazz.getSimpleName() + "is not assignable from IResource"); 075 } 076 } 077 } 078 079 /** 080 * Remove any metadata that was added by any {@code ProvidesResources} annotation 081 * present in {@code theProvider}. This method is callled from {@code RestfulService} 082 * when it is unregistering a Resource Provider. 083 * 084 * @param theProvider 085 * - Normally a {@link ca.uhn.fhir.rest.server.IResourceProvider} that might 086 * be annotated with {@link ca.uhn.fhir.model.api.annotation.ProvidesResources} 087 */ 088 public void removeProvidedResources(Object theProvider) { 089 ProvidesResources annotation = theProvider.getClass().getAnnotation(ProvidesResources.class); 090 if (annotation == null) 091 return; 092 for (Class<?> clazz : annotation.resources()) { 093 if (IBaseResource.class.isAssignableFrom(clazz)) { 094 // TODO -- not currently used but should be finished for completeness 095 } else { 096 ourLog.warn(clazz.getSimpleName() + "is not assignable from IResource"); 097 } 098 } 099 } 100}