001/** 002 * 003 * Copyright 2019 Florian Schmaus 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 org.jxmpp.strings.testframework; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.parboiled.Rule; 023import org.parboiled.parserunners.ParseRunner; 024import org.parboiled.parserunners.ReportingParseRunner; 025import org.parboiled.parserunners.TracingParseRunner; 026import org.parboiled.support.ParsingResult; 027 028public abstract class JidCorpusParser<J> { 029 030 public static final char ASCII_LINE_FEED_UNICODE_END_OF_LINE = '\n'; 031 public static final char ASCII_RECORD_SEPARATOR_UNICODE_INFORMATION_SEPARATOR_TWO = '\u001E'; 032 public static final char ASCII_UNIT_SEPARATOR_UNICODE_INFORMATION_SEPARATOR_ONE = '\u001F'; 033 public static final String END_OF_RECORD; 034 035 static { 036 char[] endOfRecordChars = {ASCII_RECORD_SEPARATOR_UNICODE_INFORMATION_SEPARATOR_TWO, 037 ASCII_LINE_FEED_UNICODE_END_OF_LINE}; 038 END_OF_RECORD = new String(endOfRecordChars); 039 } 040 041 protected static final char[] CONTROL_CHARACTERS = new char[] { 042 ASCII_RECORD_SEPARATOR_UNICODE_INFORMATION_SEPARATOR_TWO, 043 ASCII_UNIT_SEPARATOR_UNICODE_INFORMATION_SEPARATOR_ONE, 044 }; 045 046 protected static final char[] CONTROL_CHARACTERS_AND_NEWLINE; 047 048 static { 049 CONTROL_CHARACTERS_AND_NEWLINE = new char[CONTROL_CHARACTERS.length + 1]; 050 System.arraycopy(CONTROL_CHARACTERS, 0, CONTROL_CHARACTERS_AND_NEWLINE, 0, CONTROL_CHARACTERS.length); 051 CONTROL_CHARACTERS_AND_NEWLINE[CONTROL_CHARACTERS_AND_NEWLINE.length - 1] = '\n'; 052 } 053 054 private final String input; 055 private final boolean enableParserTracing; 056 057 ParsingResult<J> parsingResult; 058 private List<J> parsedJids; 059 060 /** 061 * Construct a new valid JID corpus parser. 062 * 063 * @param input the string to parse. 064 */ 065 protected JidCorpusParser(String input) { 066 this(input, false); 067 } 068 069 /** 070 * Construct a new valid JID corpus parser. 071 * 072 * @param input the string to parse. 073 * @param tracing if tracing of the parser should be enabled. 074 */ 075 protected JidCorpusParser(String input, boolean tracing) { 076 this.input = input; 077 this.enableParserTracing = tracing; 078 } 079 080 /** 081 * Parse the input. 082 * 083 * @return a list of parsed {@link ValidJid}s. 084 */ 085 public List<J> parse() { 086 final ParseRunner<J> runner; 087 if (enableParserTracing) { 088 runner = getTracingParseRunner(); 089 } else { 090 runner = getReportingParserRunner(); 091 } 092 093 parsingResult = runner.run(input); 094 parsedJids = getValidJidsFrom(parsingResult); 095 return parsedJids; 096 } 097 098 protected abstract Rule getParserRootRule(); 099 100 private ReportingParseRunner<J> getReportingParserRunner() { 101 Rule parserRootRule = getParserRootRule(); 102 ReportingParseRunner<J> runner = new ReportingParseRunner<>(parserRootRule); 103 return runner; 104 } 105 106 private TracingParseRunner<J> getTracingParseRunner() { 107 Rule parserRootRule = getParserRootRule(); 108 TracingParseRunner<J> runner = new TracingParseRunner<>(parserRootRule); 109 return runner; 110 } 111 112 private static <J> List<J> getValidJidsFrom(ParsingResult<J> parsingResult) { 113 final List<J> result = new ArrayList<>(parsingResult.valueStack.size()); 114 parsingResult.valueStack.forEach(e -> result.add(e)); 115 return result; 116 } 117 118}