/*
* Copyright 2003-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.idea.testFramework;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ResourceBundle;
import java.util.Scanner;
import java.util.StringTokenizer;
public class MpsTestDataParser implements EntryDataParser {
private final static Logger LOG = LogManager.getLogger(MpsTestDataParser.class);
@NonNls
private final static ResourceBundle BUNDLE = ResourceBundle.getBundle("jetbrains.mps.idea.core.MPSCoreBundle");
private final static String DELIMITERS = "\n\t\f\r;";
private final FileDataParser myParser;
public MpsTestDataParser(@NotNull File file) throws FileNotFoundException {
myParser = new FileDataParser(file, DELIMITERS);
}
public void close() {
myParser.close();
}
@Override
public Entry nextToken(Class<? extends Entry> aClass) throws ParseException {
try {
Entry result = aClass.newInstance();
String token = nextTokenChecked();
result.parse(new LineDataParser(token));
return result;
} catch (InstantiationException e) {
throw new ParseException(e);
} catch (IllegalAccessException e) {
throw new ParseException(e);
}
}
@NotNull
private String nextTokenChecked() throws ParseException {
String token = myParser.nextToken(DELIMITERS);
if (token == null) {
throw new ParseException("Next token cannot be read.");
}
return token;
}
@Override
public boolean hasMoreTokens() {
return myParser.hasMoreTokens();
}
public static interface InnerDataParser {
@Nullable
String nextToken(String delimiter);
int countTokens();
boolean hasMoreTokens();
}
static class LineDataParser implements InnerDataParser {
private final StringTokenizer myTokenizer;
private LineDataParser(@NotNull String string) {
myTokenizer = new StringTokenizer(string);
}
public LineDataParser(@NotNull String string, String delimiters) {
myTokenizer = new StringTokenizer(string, delimiters, false);
}
@Nullable
@Override
public String nextToken(String delimiters) {
if (!hasMoreTokens()) {
return null;
}
return myTokenizer.nextToken(delimiters);
}
@Override
public int countTokens() {
return myTokenizer.countTokens();
}
@Override
public boolean hasMoreTokens() {
return myTokenizer.hasMoreTokens();
}
}
static class FileDataParser implements InnerDataParser {
private final Scanner myScanner;
private final String myDelimiters;
private LineDataParser myParser = null;
private FileDataParser(File file, String delimiters) throws FileNotFoundException {
myScanner = new Scanner(new BufferedReader(new FileReader(file)));
myDelimiters = delimiters;
}
public void close() {
if (myScanner.hasNext()) {
LOG.warn(BUNDLE.getString("closing.stream.while.there.are.unread.tokens"));
}
myScanner.close();
}
private boolean initDataParserIfNeeded() {
while (myParser == null || !myParser.hasMoreTokens()) {
if (!myScanner.hasNextLine()) {
return false;
}
String line = myScanner.nextLine();
line = line.trim();
myParser = new LineDataParser(line, myDelimiters);
}
return true;
}
@Nullable
@Override
public String nextToken(String delimiters) {
if (!initDataParserIfNeeded()) {
return null;
}
return myParser.nextToken(delimiters);
}
@Override
public int countTokens() {
if (!initDataParserIfNeeded()) {
return 0;
}
return myParser.countTokens();
}
@Override
public boolean hasMoreTokens() {
if (!initDataParserIfNeeded()) {
return false;
}
return myParser.hasMoreTokens();
}
}
}