001/**
002The contents of this file are subject to the Mozilla Public License Version 1.1 
003(the "License"); you may not use this file except in compliance with the License. 
004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005Software distributed under the License is distributed on an "AS IS" basis, 
006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007specific language governing rights and limitations under the License. 
008
009The Original Code is "Version.java".  Description: 
010"An enumeration of supported HL7 versions" 
011
012The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0132012.  All Rights Reserved. 
014
015Contributor(s): ______________________________________. 
016
017Alternatively, the contents of this file may be used under the terms of the 
018GNU General Public License (the  "GPL"), in which case the provisions of the GPL are 
019applicable instead of those above.  If you wish to allow use of your version of this 
020file only under the terms of the GPL and not to allow others to use your version 
021of this file under the MPL, indicate your decision by deleting  the provisions above 
022and replace  them with the notice and other provisions required by the GPL License.  
023If you do not delete the provisions above, a recipient may use your version of 
024this file under either the MPL or the GPL. 
025 */
026package ca.uhn.hl7v2;
027
028import java.io.InputStream;
029import java.util.ArrayList;
030import java.util.HashMap;
031import java.util.List;
032import java.util.Map;
033import java.util.Set;
034
035import ca.uhn.hl7v2.model.GenericMessage;
036import ca.uhn.hl7v2.parser.ModelClassFactory;
037import ca.uhn.hl7v2.parser.Parser;
038
039public enum Version {
040
041        V21("2.1"), // -
042        V22("2.2"), // -
043        V23("2.3"), // -
044        V231("2.3.1"), // -
045        V24("2.4"), // -
046        V25("2.5"), // -
047        V251("2.5.1"), // -
048        V26("2.6"); // -
049
050        private String version;
051        private static ArrayList<Version> ourVersionsOnClasspath;
052        private static final Map<Version, Boolean> ourIsOnClasspath = new HashMap<Version, Boolean>();
053
054        Version(String version) {
055                this.version = version;
056        }
057
058        /**
059         * Returns a version string (e.g. "2.1", or "2.5.1")
060         */
061        public String getVersion() {
062                return version;
063        }
064
065        public String getPackageVersion() {
066                return "v" + version.replace(".", "");
067        }
068
069        /**
070         * Returns <code>true</code> if theVersion is a valid HL7
071         * version string representing a known version, e.g. "2.4", "2.6"
072         */
073        public static boolean supportsVersion(String theVersion) {
074                return versionOf(theVersion) != null;
075        }
076
077        /**
078         * @param version The version string, e.g. "2.1" or "2.6"
079         */
080        public static Version versionOf(String version) {
081                for (Version v : Version.values()) {
082                        if (v.getVersion().equals(version)) {
083                                return v;
084                        }
085                }
086                return null;
087        }
088
089        /**
090         * @param someVersions set of versions to be tested
091         * @return <code>true</code> if someVersions contain all supported HL7 versions
092         */
093        public static boolean allVersions(Set<Version> someVersions) {
094                return someVersions != null && someVersions.size() == values().length;
095        }
096
097        /**
098         * Returns true if this version is greater than the specified version
099         */
100        public boolean isGreaterThan(Version theVersion) {
101                return compareTo(theVersion) > 0;
102        }
103
104        /**
105         * Returns the newest available version of the message structure classes
106         * on the classpath, or <code>null</code> if none are found
107         */
108        public static Version latestVersion() {
109                Version[] versions = Version.values();
110                if (versions.length > 0) {
111                        return versions[versions.length - 1];
112                } else {
113                        return null;
114                }
115        }
116
117        public static Version[] asOf(Version v) {
118                List<Version> versions = new ArrayList<Version>();
119                for (Version version : Version.values()) {
120                        if (version.compareTo(v) >= 0)
121                                versions.add(version);
122                }
123                return versions.toArray(new Version[versions.size()]);
124        }
125
126        public static Version[] except(Version v) {
127                List<Version> versions = new ArrayList<Version>();
128                for (Version version : Version.values()) {
129                        if (version.compareTo(v) != 0)
130                                versions.add(version);
131                }
132                return versions.toArray(new Version[versions.size()]);
133        }
134
135        public static Version[] before(Version v) {
136                List<Version> versions = new ArrayList<Version>();
137                for (Version version : Version.values()) {
138                        if (version.compareTo(v) < 0)
139                                versions.add(version);
140                }
141                return versions.toArray(new Version[versions.size()]);
142        }
143
144        public String modelPackageName() {
145                return String
146                                .format("%s.model.%s.", getClass().getPackage().getName(), getPackageVersion());
147        }
148
149        /**
150         * Returns <code>true</code> if the structure
151         * classes for this particular version are available
152         * on the classpath.
153         */
154        public synchronized boolean available() {
155                Boolean retVal = ourIsOnClasspath.get(this);
156                if (retVal == null) {
157                        String resource = "ca/uhn/hl7v2/parser/eventmap/" + getVersion() + ".properties";
158                        InputStream in = Parser.class.getClassLoader().getResourceAsStream(resource);
159                        retVal = in != null;
160                        ourIsOnClasspath.put(this, retVal);
161                }
162                return retVal;
163        }
164        
165        /**
166         * Returns a list of all versions for which the structure JARs have been
167         * found on the classpath.
168         */
169        public static synchronized List<Version> availableVersions() {
170                if (ourVersionsOnClasspath == null) {
171                        ourVersionsOnClasspath = new ArrayList<Version>();
172                        for (Version next : values()) {
173                                if (next.available()) {
174                                        ourVersionsOnClasspath.add(next);
175                                }
176                        }
177                }
178                return ourVersionsOnClasspath;
179        }
180        
181        /**
182         * <p>
183         * Returns the lowest version for which the structure classes are found
184         * on the classes. For instance, if <code>hapi-structures-v24-[version].jar</code>
185         * is the only structure JAR on the current JVM classpath, {@link Version#V24} will
186         * be returned.
187         * <p>
188         * <p>
189         * Returns <code>null</code> if none are found
190         * </p>
191         */
192        public static Version lowestAvailableVersion() {
193                List<Version> availableVersions = availableVersions();
194                if (availableVersions.size() >0) {
195                        return availableVersions.get(0);
196                } else {
197                        return null;
198                }
199        }
200
201        /**
202         * <p>
203         * Returns the highest version for which the structure classes are found
204         * on the classes. For instance, if <code>hapi-structures-v24-[version].jar</code>
205         * is the only structure JAR on the current JVM classpath, {@link Version#V24} will
206         * be returned.
207         * <p>
208         * </>
209         * If no structure JARs at all are found, returns a default value of
210         * {@link Version#V25}
211         * </p>
212         */
213        public static Version highestAvailableVersionOrDefault() {
214                List<Version> availableVersions = availableVersions();
215                if (availableVersions.size() >0) {
216                        return availableVersions.get(availableVersions.size() - 1);
217                } else {
218                        return Version.V25;
219                }
220        }
221
222        /**
223         * Construct and return a new {@link GenericMessage} for the given version
224         */
225        public GenericMessage newGenericMessage(ModelClassFactory mcf) {
226                switch (this) {
227                case V21:
228                        return new GenericMessage.V21(mcf);
229                case V22:
230                        return new GenericMessage.V22(mcf);
231                case V23:
232                        return new GenericMessage.V23(mcf);
233                case V231:
234                        return new GenericMessage.V231(mcf);
235                case V24:
236                        return new GenericMessage.V24(mcf);
237                case V25:
238                        return new GenericMessage.V25(mcf);
239                case V251:
240                        return new GenericMessage.V251(mcf);
241                case V26:
242                        return new GenericMessage.V26(mcf);
243                default:
244                        throw new Error("Unknown version (this is a HAPI bug): " + this.getVersion());
245                }
246        }
247        
248}