001    /*
002     * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package javax.lang.model;
027    
028    import java.util.Collections;
029    import java.util.Set;
030    import java.util.HashSet;
031    
032    /**
033     * Source versions of the Java™ programming language.
034     *
035     * See <a
036     * href="http://java.sun.com/docs/books/jls/">http://java.sun.com/docs/books/jls/</a>
037     * for information on editions of <i>The Java&trade; Language
038     * Specification</i>, including updates and clarifications.
039     *
040     * <p>Note that additional source version constants will be added to
041     * model future releases of the language.
042     *
043     * @author Joseph D. Darcy
044     * @author Scott Seligman
045     * @author Peter von der Ah&eacute;
046     * @since 1.6
047     */
048    public enum SourceVersion {
049        /*
050         * Summary of language evoluation
051         * 1.1: nested classes
052         * 1.2: strictfp
053         * 1.3: no changes
054         * 1.4: assert
055         * 1.5: annotations, generics, autoboxing, var-args...
056         * 1.6: no changes
057         */
058    
059        /**
060         * The original version.
061         *
062         * The language described in the first edition of <i>The
063         * Java&trade; Language Specification</i>.
064         */
065        RELEASE_0,
066    
067        /**
068         * The version recognized by the Java Platform 1.1.
069         *
070         * The language is {@code RELEASE_0} <a
071         * href="http://java.sun.com/docs/books/jls/first_edition/html/1.1Update.html">augmented</a>
072         * with nested classes.
073         */
074        RELEASE_1,
075    
076        /**
077         * The version recognized by the Java 2 Platform, Standard Edition,
078         * v 1.2.
079         *
080         * The language described in <i>The Java&trade; Language
081         * Specification, Second Edition</i>, which includes the {@code
082         * strictfp} modifier.
083         */
084        RELEASE_2,
085    
086        /**
087         * The version recognized by the Java 2 Platform, Standard Edition,
088         * v 1.3.
089         *
090         * No major changes from {@code RELEASE_2}.
091         */
092        RELEASE_3,
093    
094        /**
095         * The version recognized by the Java 2 Platform, Standard Edition,
096         * v 1.4.
097         *
098         * Added a simple assertion facility.
099         */
100        RELEASE_4,
101    
102        /**
103         * The version recognized by the Java 2 Platform, Standard
104         * Edition 5.0.
105         *
106         * The language described in <i>The Java&trade; Language
107         * Specification, Third Edition</i>.  First release to support
108         * generics, annotations, autoboxing, var-args, enhanced {@code
109         * for} loop, and hexadecimal floating-point literals.
110         */
111        RELEASE_5,
112    
113        /**
114         * The version recognized by the Java Platform, Standard Edition
115         * 6.
116         *
117         * No major changes from {@code RELEASE_5}.
118         */
119        RELEASE_6,
120    
121        /**
122         * The version recognized by the Java Platform, Standard Edition
123         * 7.
124         *
125         * @since 1.7
126         */
127        RELEASE_7;
128    
129        // Note that when adding constants for newer releases, the
130        // behavior of latest() and latestSupported() must be updated too.
131    
132        /**
133         * Returns the latest source version that can be modeled.
134         *
135         * @return the latest source version that can be modeled
136         */
137        public static SourceVersion latest() {
138            return RELEASE_7;
139        }
140    
141        private static final SourceVersion latestSupported = getLatestSupported();
142    
143        private static SourceVersion getLatestSupported() {
144            try {
145                String specVersion = System.getProperty("java.specification.version");
146                if ("1.7".equals(specVersion))
147                    return RELEASE_7;
148                else if ("1.6".equals(specVersion))
149                    return RELEASE_6;
150            } catch (SecurityException se) {}
151    
152            return RELEASE_5;
153        }
154    
155        /**
156         * Returns the latest source version fully supported by the
157         * current execution environment.  {@code RELEASE_5} or later must
158         * be returned.
159         *
160         * @return the latest source version that is fully supported
161         */
162        public static SourceVersion latestSupported() {
163            return latestSupported;
164        }
165    
166        /**
167         * Returns whether or not {@code name} is a syntactically valid
168         * identifier (simple name) or keyword in the latest source
169         * version.  The method returns {@code true} if the name consists
170         * of an initial character for which {@link
171         * Character#isJavaIdentifierStart(int)} returns {@code true},
172         * followed only by characters for which {@link
173         * Character#isJavaIdentifierPart(int)} returns {@code true}.
174         * This pattern matches regular identifiers, keywords, and the
175         * literals {@code "true"}, {@code "false"}, and {@code "null"}.
176         * The method returns {@code false} for all other strings.
177         *
178         * @param name the string to check
179         * @return {@code true} if this string is a
180         * syntactically valid identifier or keyword, {@code false}
181         * otherwise.
182         */
183        public static boolean isIdentifier(CharSequence name) {
184            String id = name.toString();
185    
186            if (id.length() == 0) {
187                return false;
188            }
189            int cp = id.codePointAt(0);
190            if (!Character.isJavaIdentifierStart(cp)) {
191                return false;
192            }
193            for (int i = Character.charCount(cp);
194                    i < id.length();
195                    i += Character.charCount(cp)) {
196                cp = id.codePointAt(i);
197                if (!Character.isJavaIdentifierPart(cp)) {
198                    return false;
199                }
200            }
201            return true;
202        }
203    
204        /**
205         *  Returns whether or not {@code name} is a syntactically valid
206         *  qualified name in the latest source version.  Unlike {@link
207         *  #isIdentifier isIdentifier}, this method returns {@code false}
208         *  for keywords and literals.
209         *
210         * @param name the string to check
211         * @return {@code true} if this string is a
212         * syntactically valid name, {@code false} otherwise.
213         * @jls3 6.2 Names and Identifiers
214         */
215        public static boolean isName(CharSequence name) {
216            String id = name.toString();
217    
218            for(String s : id.split("\\.", -1)) {
219                if (!isIdentifier(s) || isKeyword(s))
220                    return false;
221            }
222            return true;
223        }
224    
225        private final static Set<String> keywords;
226        static {
227            Set<String> s = new HashSet<String>();
228            String [] kws = {
229                "abstract", "continue",     "for",          "new",          "switch",
230                "assert",   "default",      "if",           "package",      "synchronized",
231                "boolean",  "do",           "goto",         "private",      "this",
232                "break",    "double",       "implements",   "protected",    "throw",
233                "byte",     "else",         "import",       "public",       "throws",
234                "case",     "enum",         "instanceof",   "return",       "transient",
235                "catch",    "extends",      "int",          "short",        "try",
236                "char",     "final",        "interface",    "static",       "void",
237                "class",    "finally",      "long",         "strictfp",     "volatile",
238                "const",    "float",        "native",       "super",        "while",
239                // literals
240                "null",     "true",         "false"
241            };
242            for(String kw : kws)
243                s.add(kw);
244            keywords = Collections.unmodifiableSet(s);
245        }
246    
247        /**
248         *  Returns whether or not {@code s} is a keyword or literal in the
249         *  latest source version.
250         *
251         * @param s the string to check
252         * @return {@code true} if {@code s} is a keyword or literal, {@code false} otherwise.
253         */
254        public static boolean isKeyword(CharSequence s) {
255            String keywordOrLiteral = s.toString();
256            return keywords.contains(keywordOrLiteral);
257        }
258    }