001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright 2005-2011 The ConQAT Project                                   |
004|                                                                          |
005| Licensed under the Apache License, Version 2.0 (the "License");          |
006| you may not use this file except in compliance with the License.         |
007| You may obtain a copy of the License at                                  |
008|                                                                          |
009|    http://www.apache.org/licenses/LICENSE-2.0                            |
010|                                                                          |
011| Unless required by applicable law or agreed to in writing, software      |
012| distributed under the License is distributed on an "AS IS" BASIS,        |
013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014| See the License for the specific language governing permissions and      |
015| limitations under the License.                                           |
016+-------------------------------------------------------------------------*/
017package eu.cqse.check.framework.scanner;
018
019import java.io.File;
020import java.io.FileReader;
021import java.io.IOException;
022import java.io.Reader;
023import java.io.StringReader;
024
025import eu.cqse.check.framework.scanner.ETokenType.ETokenClass;
026
027/**
028 * This factory class is the central access point to the scanner framework. It
029 * offers different methods for constructing strict and lenient scanners for
030 * different languages and different input formats.
031 * <p>
032 * Every scanner is associated with an origin id that is attached to every token
033 * created by this scanner. It identifies the resource the tokens stem from.
034 * However, the factory does not interpret the content of the originId but
035 * merely passes it on to the scanners (and thus ultimately to the tokens). The
036 * caller of the factory methods in this class thus needs to make sure that the
037 * originIds are sane.
038 * 
039 * This factory can construct strict scanners (interface {@link IScanner}) and
040 * lenient scanners (interface {@link ILenientScanner}). Strict scanners throw
041 * {@link ScannerException}s if they encounter input they cannot recognize.
042 * Lenient scanners do not throw {@link ScannerException}s, but instead return
043 * tokens with a token type of token class {@link ETokenClass#ERROR}, specifying
044 * the type of error encountered, and resume scanning.
045 */
046public class ScannerFactory {
047
048        /**
049         * prevent instantiation
050         */
051        private ScannerFactory() {
052                // prevent instantiation
053        }
054
055        /**
056         * Create a new strict scanner for a file. Tokens generated by this scanner will
057         * carry the canonical path of the file as origin id.
058         * 
059         * @param language
060         *            implementation language
061         * @param file
062         *            the file to scan
063         * @return a new strict scanner
064         */
065        public static IScanner newScanner(ELanguage language, File file) throws IOException {
066                return strict(newLenientScanner(language, file));
067        }
068
069        /**
070         * Create a new lenient scanner for a file. Tokens generated by this scanner
071         * will carry the canonical path of the file as originId.
072         * 
073         * @param language
074         *            implementation language
075         * @param file
076         *            the file to scan
077         * @return a new lenient scanner
078         */
079        public static ILenientScanner newLenientScanner(ELanguage language, File file) throws IOException {
080                return newLenientScanner(language, new FileReader(file), file.getCanonicalPath());
081        }
082
083        /**
084         * Create a new strict scanner that scans a string.
085         * 
086         * @param language
087         *            implementation language
088         * @param input
089         *            the string to scan
090         * @param originId
091         *            origin id that denotes the resource the tokens stem from
092         * @return a new strict scanner
093         */
094        public static IScanner newScanner(ELanguage language, String input, String originId) {
095                return strict(newLenientScanner(language, input, originId));
096        }
097
098        /**
099         * Create a new lenient scanner that scans a string.
100         * 
101         * @param language
102         *            implementation language
103         * @param input
104         *            the string to scan
105         * @param originId
106         *            origin id that denotes the resource the tokens stem from
107         * @return a new lenient scanner
108         */
109        public static ILenientScanner newLenientScanner(ELanguage language, String input, String originId) {
110                return newLenientScanner(language, new StringReader(input), originId);
111        }
112
113        /**
114         * Create a new strict scanner that uses the specified reader.
115         * 
116         * @param language
117         *            implementation language
118         * @param reader
119         *            the reader to read the input from
120         * @param originId
121         *            origin id that denotes the resource the tokens stem from
122         * @return a new strict scanner
123         */
124        public static IScanner newScanner(ELanguage language, Reader reader, String originId) {
125                return strict(newLenientScanner(language, reader, originId));
126        }
127
128        /**
129         * Create a new lenient scanner that uses the specified reader.
130         * 
131         * @param language
132         *            implementation language
133         * @param reader
134         *            the reader to read the input from
135         * @param originId
136         *            origin id that denotes the resource the tokens stem from
137         * @return a new lenient scanner
138         */
139        public static ILenientScanner newLenientScanner(ELanguage language, Reader reader, String originId) {
140                switch (language) {
141                case JAVA:
142                        return new JavaScanner(reader, originId);
143                case CS:
144                        return new CSScanner(reader, originId);
145                case CPP:
146                        return new CPPScanner(reader, originId);
147                case VB:
148                        return new VBScanner(reader, originId);
149                case PL1:
150                        return new PL1Scanner(reader, originId);
151                case COBOL:
152                        return new CobolScanner(reader, originId);
153                case ABAP:
154                        return new ABAPScanner(reader, originId);
155                case ADA:
156                        return new AdaScanner(reader, originId);
157                case TEXT:
158                case NL_REQUIREMENTS:
159                case NL_TESTS:
160                case SIMULINK:
161                case ABAP_DDIC:
162                        return new TextScanner(reader, originId);
163                case XML:
164                case HANA_VIEW:
165                        return new XMLScanner(reader, originId);
166                case PLSQL:
167                        return new PLSQLScanner(reader, originId);
168                case PYTHON:
169                        return new PythonScanner(reader, originId);
170                case TSQL:
171                        return new TSQLScanner(reader, originId);
172                case MATLAB:
173                        return new MatlabScanner(reader, originId);
174                case PHP:
175                        return new PHPScanner(reader, originId);
176                case RUBY:
177                        return new RubyScanner(reader, originId);
178                case JAVASCRIPT:
179                        return new JavaScriptScanner(reader, originId);
180                case MTEXT:
181                        return new MTextScanner(reader, originId);
182                case LINE:
183                        return new LineScanner(reader, originId);
184                case JPL:
185                        return new JPLScanner(reader, originId);
186                case DELPHI:
187                        return new DelphiScanner(reader, originId);
188                case IEC61131:
189                        return new Iec61131Scanner(reader, originId);
190                case FORTRAN:
191                        return new FortranScanner(reader, originId);
192                case XTEND:
193                        return new XtendScanner(reader, originId);
194                case OCAML:
195                        return new OCamlScanner(reader, originId);
196                case SWIFT:
197                        return new SwiftScanner(reader, originId);
198                case GROOVY:
199                        return new GroovyScanner(reader, originId);
200                case SQLSCRIPT:
201                        return new HanaSQLScriptScanner(reader, originId);
202                case OPEN_CL:
203                        return new OpenCLScanner(reader, originId);
204                case RUST:
205                        return new RustScanner(reader, originId);
206                case GOSU:
207                        return new GosuScanner(reader, originId);
208                case OSCRIPT:
209                        return new OScriptScanner(reader, originId);
210                case KOTLIN:
211                        return new KotlinScanner(reader, originId);
212                case JAVADOC:
213                        return new JavaDocScanner(reader, originId);
214                case OBJECTIVE_C:
215                        return new ObjectiveCScanner(reader, originId);
216                case GO:
217                        return new GoScanner(reader, originId);
218                default:
219                        throw new IllegalArgumentException("Language '" + language + "' not supported.");
220                }
221        }
222
223        /**
224         * Wraps an {@link ILenientScanner} scanner with a {@link StrictScanner}.
225         */
226        public static IScanner strict(ILenientScanner scanner) {
227                return new StrictScanner(scanner);
228        }
229}