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}