001package ca.uhn.fhir.rest.server;
002
003import java.util.Collections;
004
005/*
006 * #%L
007 * HAPI FHIR - Core Library
008 * %%
009 * Copyright (C) 2014 - 2017 University Health Network
010 * %%
011 * Licensed under the Apache License, Version 2.0 (the "License");
012 * you may not use this file except in compliance with the License.
013 * You may obtain a copy of the License at
014 * 
015 *      http://www.apache.org/licenses/LICENSE-2.0
016 * 
017 * Unless required by applicable law or agreed to in writing, software
018 * distributed under the License is distributed on an "AS IS" BASIS,
019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020 * See the License for the specific language governing permissions and
021 * limitations under the License.
022 * #L%
023 */
024
025import java.util.HashMap;
026import java.util.Map;
027
028import ca.uhn.fhir.context.FhirContext;
029import ca.uhn.fhir.parser.IParser;
030
031public enum EncodingEnum {
032
033        JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_JSON, Constants.FORMAT_JSON) {
034                @Override
035                public IParser newParser(FhirContext theContext) {
036                        return theContext.newJsonParser();
037                }
038        },
039
040        XML(Constants.CT_FHIR_XML, Constants.CT_FHIR_XML_NEW, Constants.CT_ATOM_XML, Constants.FORMAT_XML) {
041                @Override
042                public IParser newParser(FhirContext theContext) {
043                        return theContext.newXmlParser();
044                }
045        }
046
047        ;
048
049        /** "xml" */
050        public static final String XML_PLAIN_STRING = "xml";
051        /** "json" */
052        public  static final String JSON_PLAIN_STRING = "json";
053        
054        private static Map<String, EncodingEnum> ourContentTypeToEncoding;
055        private static Map<String, EncodingEnum> ourContentTypeToEncodingNonLegacy;
056        private static Map<String, EncodingEnum> ourContentTypeToEncodingStrict;
057
058        static {
059                ourContentTypeToEncoding = new HashMap<String, EncodingEnum>();
060                ourContentTypeToEncodingNonLegacy = new HashMap<String, EncodingEnum>();
061                
062                for (EncodingEnum next : values()) {
063                        ourContentTypeToEncoding.put(next.getBundleContentType(), next);
064                        ourContentTypeToEncoding.put(next.myResourceContentTypeNonLegacy, next);
065                        ourContentTypeToEncoding.put(next.myResourceContentTypeLegacy, next);
066                        ourContentTypeToEncodingNonLegacy.put(next.myResourceContentTypeNonLegacy, next);
067
068                        /*
069                         * See #346
070                         */
071                        ourContentTypeToEncoding.put(next.myResourceContentTypeNonLegacy.replace('+', ' '), next);
072                        ourContentTypeToEncoding.put(next.myResourceContentTypeLegacy.replace('+', ' '), next);
073                        ourContentTypeToEncodingNonLegacy.put(next.myResourceContentTypeNonLegacy.replace('+', ' '), next);
074
075                }
076
077                // Add before we add the lenient ones
078                ourContentTypeToEncodingStrict = Collections.unmodifiableMap(new HashMap<String, EncodingEnum>(ourContentTypeToEncoding));
079
080                /*
081                 * These are wrong, but we add them just to be tolerant of other
082                 * people's mistakes
083                 */
084                ourContentTypeToEncoding.put("application/json", JSON);
085                ourContentTypeToEncoding.put("application/xml", XML);
086                ourContentTypeToEncoding.put("text/json", JSON);
087                ourContentTypeToEncoding.put("text/xml", XML);
088
089                /*
090                 * Plain values, used for parameter values
091                 */
092                ourContentTypeToEncoding.put(JSON_PLAIN_STRING, JSON);
093                ourContentTypeToEncoding.put(XML_PLAIN_STRING, XML);
094
095                ourContentTypeToEncodingNonLegacy = Collections.unmodifiableMap(ourContentTypeToEncodingNonLegacy);
096
097        }
098
099        private String myBundleContentType;
100        private String myFormatContentType;
101        private String myResourceContentTypeNonLegacy;
102        private String myResourceContentTypeLegacy;
103
104        EncodingEnum(String theResourceContentTypeLegacy, String theResourceContentType, String theBundleContentType, String theFormatContentType) {
105                myResourceContentTypeLegacy = theResourceContentTypeLegacy;
106                myResourceContentTypeNonLegacy = theResourceContentType;
107                myBundleContentType = theBundleContentType;
108                myFormatContentType = theFormatContentType;
109        }
110
111        public String getBundleContentType() {
112                return myBundleContentType;
113        }
114
115        public String getFormatContentType() {
116                return myFormatContentType;
117        }
118
119        public String getRequestContentType() {
120                return myFormatContentType;
121        }
122
123        /**
124         * Will return application/xml+fhir style
125         */
126        public String getResourceContentType() {
127                return myResourceContentTypeLegacy;
128        }
129
130        /**
131         * Will return application/fhir+xml style
132         */
133        public String getResourceContentTypeNonLegacy() {
134                return myResourceContentTypeNonLegacy;
135        }
136
137        public abstract IParser newParser(FhirContext theContext);
138
139        /**
140         * Returns the encoding for a given content type, or <code>null</code> if no encoding
141         * is found. 
142         * <p>
143         * <b>This method is lenient!</b> Things like "application/xml" will return {@link EncodingEnum#XML}
144         * even if the "+fhir" part is missing from the expected content type.
145         * </p>
146         */
147        public static EncodingEnum forContentType(String theContentType) {
148                return ourContentTypeToEncoding.get(theContentType);
149        }
150
151        /**
152         * Returns the encoding for a given content type, or <code>null</code> if no encoding
153         * is found. 
154         * <p>
155         * <b>This method is NOT lenient!</b> Things like "application/xml" will return <code>null</code>
156         * </p>
157         * @see #forContentType(String)
158         */
159        public static EncodingEnum forContentTypeStrict(String theContentType) {
160                return ourContentTypeToEncodingStrict.get(theContentType);
161        }
162
163        public static boolean isNonLegacy(String theFormat) {
164                return ourContentTypeToEncodingNonLegacy.containsKey(theFormat);
165        }
166
167
168}