001package ca.uhn.fhir.context;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2017 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        ;
048
049        private final FhirVersionEnum myEquivalent;
050        private final boolean myIsRi;
051        private volatile Boolean myPresentOnClasspath;
052        private final String myVersionClass;
053        private volatile IFhirVersion myVersionImplementation;
054        private String myFhirVersionString;
055
056        FhirVersionEnum(String theVersionClass, FhirVersionEnum theEquivalent, boolean theIsRi, IVersionProvider theVersionExtractor) {
057                myVersionClass = theVersionClass;
058                myEquivalent = theEquivalent;
059                myFhirVersionString = theVersionExtractor.provideVersion();
060                myIsRi = theIsRi;
061        }
062
063        public String getFhirVersionString() {
064                return myFhirVersionString;
065        }
066
067        public IFhirVersion getVersionImplementation() {
068                if (!isPresentOnClasspath()) {
069                        throw new IllegalStateException("Version " + name() + " is not present on classpath");
070                }
071                if (myVersionImplementation == null) {
072                        try {
073                                myVersionImplementation = (IFhirVersion) Class.forName(myVersionClass).newInstance();
074                        } catch (Exception e) {
075                                throw new InternalErrorException("Failed to instantiate FHIR version " + name(), e);
076                        }
077                }
078                return myVersionImplementation;
079        }
080
081        public boolean isEquivalentTo(FhirVersionEnum theVersion) {
082                if (this.equals(theVersion)) {
083                        return true;
084                }
085                if (myEquivalent != null) {
086                        return myEquivalent.equals(theVersion);
087                }
088                return false;
089        }
090
091        public boolean isNewerThan(FhirVersionEnum theVersion) {
092                return !isEquivalentTo(theVersion) && ordinal() > theVersion.ordinal();
093        }
094
095        public boolean isOlderThan(FhirVersionEnum theVersion) {
096                return !isEquivalentTo(theVersion) && ordinal() < theVersion.ordinal();
097        }
098
099        /**
100         * Returns true if the given version is present on the classpath
101         */
102        public boolean isPresentOnClasspath() {
103                Boolean retVal = myPresentOnClasspath;
104                if (retVal == null) {
105                        try {
106                                Class.forName(myVersionClass);
107                                retVal = true;
108                        } catch (Exception e) {
109                                retVal = false;
110                        }
111                        myPresentOnClasspath = retVal;
112                }
113                return retVal;
114        }
115
116        /**
117         * Is this version using the HL7.org RI structures?
118         */
119        public boolean isRi() {
120                return myIsRi;
121        }
122
123        private static class Version implements IVersionProvider {
124
125                public Version(String theVersion) {
126                        super();
127                        myVersion = theVersion;
128                }
129
130                private String myVersion;
131
132                @Override
133                public String provideVersion() {
134                        return myVersion;
135                }
136
137        }
138
139        private interface IVersionProvider {
140                String provideVersion();
141        }
142
143        /**
144         * This class attempts to read the FHIR version from the actual model
145         * classes in order to supply an accurate version string even over time
146         *
147         */
148        private static class Dstu3Version implements IVersionProvider {
149
150                public Dstu3Version() {
151                        try {
152                                Class<?> c = Class.forName("org.hl7.fhir.dstu3.model.Constants");
153                                myVersion = (String) c.getDeclaredField("VERSION").get(null);
154                        } catch (Exception e) {
155                                myVersion = "3.0.1";
156                        }
157                }
158
159                private String myVersion;
160
161                @Override
162                public String provideVersion() {
163                        return myVersion;
164                }
165
166        }
167
168        private static class R4Version implements IVersionProvider {
169
170                public R4Version() {
171                        try {
172                                Class<?> c = Class.forName("org.hl7.fhir.r4.model.Constants");
173                                myVersion = (String) c.getDeclaredField("VERSION").get(null);
174                        } catch (Exception e) {
175                                myVersion = "4.0.0";
176                        }
177                }
178
179                private String myVersion;
180
181                @Override
182                public String provideVersion() {
183                        return myVersion;
184                }
185
186        }
187
188}