View Javadoc
1   package ca.uhn.fhir.context;
2   
3   /*
4    * #%L
5    * HAPI FHIR - Core Library
6    * %%
7    * Copyright (C) 2014 - 2018 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   * http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import ca.uhn.fhir.model.api.IFhirVersion;
24  import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
25  
26  public enum FhirVersionEnum {
27  
28  	/*
29  	 * ***********************
30  	 * Don't auto-sort this type!!!
31  	 *
32  	 * Or more accurately, entries should be sorted from OLDEST FHIR release
33  	 * to NEWEST FHIR release instead of alphabetically
34  	 * ***********************
35  	 */
36  
37  	DSTU2("ca.uhn.fhir.model.dstu2.FhirDstu2", null, false, new Version("1.0.2")),
38  
39  	DSTU2_HL7ORG("org.hl7.fhir.instance.FhirDstu2Hl7Org", DSTU2, true, new Version("1.0.2")),
40  
41  	DSTU2_1("org.hl7.fhir.dstu2016may.hapi.ctx.FhirDstu2_1", null, true, new Version("1.4.0")),
42  
43  	DSTU3("org.hl7.fhir.dstu3.hapi.ctx.FhirDstu3", null, true, new Dstu3Version()),
44  
45  	R4("org.hl7.fhir.r4.hapi.ctx.FhirR4", null, true, new R4Version()),;
46  
47  	private final FhirVersionEnum myEquivalent;
48  	private final boolean myIsRi;
49  	private final String myVersionClass;
50  	private volatile Boolean myPresentOnClasspath;
51  	private volatile IFhirVersion myVersionImplementation;
52  	private String myFhirVersionString;
53  
54  	FhirVersionEnum(String theVersionClass, FhirVersionEnum theEquivalent, boolean theIsRi, IVersionProvider theVersionExtractor) {
55  		myVersionClass = theVersionClass;
56  		myEquivalent = theEquivalent;
57  		myFhirVersionString = theVersionExtractor.provideVersion();
58  		myIsRi = theIsRi;
59  	}
60  
61  	public String getFhirVersionString() {
62  		return myFhirVersionString;
63  	}
64  
65  	public IFhirVersion getVersionImplementation() {
66  		if (!isPresentOnClasspath()) {
67  			throw new IllegalStateException("Version " + name() + " is not present on classpath");
68  		}
69  		if (myVersionImplementation == null) {
70  			try {
71  				myVersionImplementation = (IFhirVersion) Class.forName(myVersionClass).newInstance();
72  			} catch (Exception e) {
73  				throw new InternalErrorException("Failed to instantiate FHIR version " + name(), e);
74  			}
75  		}
76  		return myVersionImplementation;
77  	}
78  
79  	public boolean isEqualOrNewerThan(FhirVersionEnum theVersion) {
80  		return ordinal() >= theVersion.ordinal();
81  	}
82  
83  	public boolean isEquivalentTo(FhirVersionEnum theVersion) {
84  		if (this.equals(theVersion)) {
85  			return true;
86  		}
87  		if (myEquivalent != null) {
88  			return myEquivalent.equals(theVersion);
89  		}
90  		return false;
91  	}
92  
93  	public boolean isNewerThan(FhirVersionEnum theVersion) {
94  		return !isEquivalentTo(theVersion) && ordinal() > theVersion.ordinal();
95  	}
96  
97  	public boolean isOlderThan(FhirVersionEnum theVersion) {
98  		return !isEquivalentTo(theVersion) && ordinal() < theVersion.ordinal();
99  	}
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 }