001package ca.uhn.fhir.context; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2018 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 ca.uhn.fhir.model.api.IFhirVersion; 024import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 025 026public enum FhirVersionEnum { 027 028 /* 029 * *********************** 030 * Don't auto-sort this type!!! 031 * 032 * Or more accurately, entries should be sorted from OLDEST FHIR release 033 * to NEWEST FHIR release instead of alphabetically 034 * *********************** 035 */ 036 037 DSTU2("ca.uhn.fhir.model.dstu2.FhirDstu2", null, false, new Version("1.0.2")), 038 039 DSTU2_HL7ORG("org.hl7.fhir.instance.FhirDstu2Hl7Org", DSTU2, true, new Version("1.0.2")), 040 041 DSTU2_1("org.hl7.fhir.dstu2016may.hapi.ctx.FhirDstu2_1", null, true, new Version("1.4.0")), 042 043 DSTU3("org.hl7.fhir.dstu3.hapi.ctx.FhirDstu3", null, true, new Dstu3Version()), 044 045 R4("org.hl7.fhir.r4.hapi.ctx.FhirR4", null, true, new R4Version()),; 046 047 private final FhirVersionEnum myEquivalent; 048 private final boolean myIsRi; 049 private final String myVersionClass; 050 private volatile Boolean myPresentOnClasspath; 051 private volatile IFhirVersion myVersionImplementation; 052 private String myFhirVersionString; 053 054 FhirVersionEnum(String theVersionClass, FhirVersionEnum theEquivalent, boolean theIsRi, IVersionProvider theVersionExtractor) { 055 myVersionClass = theVersionClass; 056 myEquivalent = theEquivalent; 057 myFhirVersionString = theVersionExtractor.provideVersion(); 058 myIsRi = theIsRi; 059 } 060 061 public String getFhirVersionString() { 062 return myFhirVersionString; 063 } 064 065 public IFhirVersion getVersionImplementation() { 066 if (!isPresentOnClasspath()) { 067 throw new IllegalStateException("Version " + name() + " is not present on classpath"); 068 } 069 if (myVersionImplementation == null) { 070 try { 071 myVersionImplementation = (IFhirVersion) Class.forName(myVersionClass).newInstance(); 072 } catch (Exception e) { 073 throw new InternalErrorException("Failed to instantiate FHIR version " + name(), e); 074 } 075 } 076 return myVersionImplementation; 077 } 078 079 public boolean isEqualOrNewerThan(FhirVersionEnum theVersion) { 080 return ordinal() >= theVersion.ordinal(); 081 } 082 083 public boolean isEquivalentTo(FhirVersionEnum theVersion) { 084 if (this.equals(theVersion)) { 085 return true; 086 } 087 if (myEquivalent != null) { 088 return myEquivalent.equals(theVersion); 089 } 090 return false; 091 } 092 093 public boolean isNewerThan(FhirVersionEnum theVersion) { 094 return !isEquivalentTo(theVersion) && ordinal() > theVersion.ordinal(); 095 } 096 097 public boolean isOlderThan(FhirVersionEnum theVersion) { 098 return !isEquivalentTo(theVersion) && ordinal() < theVersion.ordinal(); 099 } 100 101 /** 102 * Returns true if the given version is present on the classpath 103 */ 104 public boolean isPresentOnClasspath() { 105 Boolean retVal = myPresentOnClasspath; 106 if (retVal == null) { 107 try { 108 Class.forName(myVersionClass); 109 retVal = true; 110 } catch (Exception e) { 111 retVal = false; 112 } 113 myPresentOnClasspath = retVal; 114 } 115 return retVal; 116 } 117 118 /** 119 * Is this version using the HL7.org RI structures? 120 */ 121 public boolean isRi() { 122 return myIsRi; 123 } 124 125 public FhirContext newContext() { 126 switch (this) { 127 case DSTU2: 128 return FhirContext.forDstu2(); 129 case DSTU2_HL7ORG: 130 return FhirContext.forDstu2Hl7Org(); 131 case DSTU2_1: 132 return FhirContext.forDstu2_1(); 133 case DSTU3: 134 return FhirContext.forDstu3(); 135 case R4: 136 return FhirContext.forR4(); 137 } 138 throw new IllegalStateException("Unknown version: " + this); // should not happen 139 } 140 141 /** 142 * Returns the {@link FhirVersionEnum} which corresponds to a specific version of 143 * FHIR. Partial version strings (e.g. "3.0") are acceptable. 144 * 145 * @return Returns null if no version exists matching the given string 146 */ 147 public static FhirVersionEnum forVersionString(String theVersionString) { 148 for (FhirVersionEnum next : values()) { 149 if (next.getFhirVersionString().startsWith(theVersionString)) { 150 return next; 151 } 152 } 153 return null; 154 } 155 156 private interface IVersionProvider { 157 String provideVersion(); 158 } 159 160 private static class Version implements IVersionProvider { 161 162 private String myVersion; 163 164 public Version(String theVersion) { 165 super(); 166 myVersion = theVersion; 167 } 168 169 @Override 170 public String provideVersion() { 171 return myVersion; 172 } 173 174 } 175 176 /** 177 * This class attempts to read the FHIR version from the actual model 178 * classes in order to supply an accurate version string even over time 179 */ 180 private static class Dstu3Version implements IVersionProvider { 181 182 private String myVersion; 183 184 Dstu3Version() { 185 try { 186 Class<?> c = Class.forName("org.hl7.fhir.dstu3.model.Constants"); 187 myVersion = (String) c.getDeclaredField("VERSION").get(null); 188 } catch (Exception e) { 189 myVersion = "3.0.1"; 190 } 191 } 192 193 @Override 194 public String provideVersion() { 195 return myVersion; 196 } 197 198 } 199 200 private static class R4Version implements IVersionProvider { 201 202 private String myVersion; 203 204 R4Version() { 205 try { 206 Class<?> c = Class.forName("org.hl7.fhir.r4.model.Constants"); 207 myVersion = (String) c.getDeclaredField("VERSION").get(null); 208 } catch (Exception e) { 209 myVersion = "4.0.0"; 210 } 211 } 212 213 @Override 214 public String provideVersion() { 215 return myVersion; 216 } 217 218 } 219 220}