001package eu.cqse.check.framework.core.util; 002 003import java.util.EnumSet; 004import java.util.regex.Pattern; 005import java.util.regex.PatternSyntaxException; 006 007import org.conqat.lib.commons.string.StringUtils; 008 009import eu.cqse.check.framework.core.CheckException; 010import eu.cqse.check.framework.scanner.ETokenType; 011import eu.cqse.check.framework.scanner.IToken; 012 013/** 014 * Utilities for the custom check framework. 015 */ 016public class CheckUtils { 017 018 /** Boolean operator types. */ 019 public static final EnumSet<ETokenType> BOOLEAN_OPERATOR_TYPES = EnumSet.of(ETokenType.ANDAND, ETokenType.OROR, 020 ETokenType.AND, ETokenType.OR, ETokenType.XOR); 021 022 /** String and character literal types. */ 023 public static final EnumSet<ETokenType> STRING_LITERALS = EnumSet.of(ETokenType.CHARACTER_LITERAL, 024 ETokenType.STRING_LITERAL); 025 026 /** 027 * String that is used to separate single parts of unique check identifiers. 028 */ 029 private static final String SEPARATOR = "#:#"; 030 031 /** Constructs a unique identifier out of the given group name and name. */ 032 public static String buildIdentifier(String categoryName, String groupName, String name) { 033 StringBuilder builder = new StringBuilder(); 034 builder.append(categoryName); 035 builder.append(SEPARATOR); 036 builder.append(groupName); 037 builder.append(SEPARATOR); 038 builder.append(name); 039 return builder.toString(); 040 } 041 042 /** 043 * Gets the text of an character/string literal token without quotes. 044 * 045 * @return the unquoted literal text or <code>null</code> if token is not of 046 * type {@link ETokenType#CHARACTER_LITERAL} 047 */ 048 public static String getUnquotedTextForCharacterLiteral(IToken token) { 049 if (!STRING_LITERALS.contains(token.getType())) { 050 return null; 051 } 052 return token.getText().replaceAll("^(('|\"|$*/)*)|(('|\"|/$*)*)$", StringUtils.EMPTY_STRING); 053 } 054 055 /** 056 * Compiles a {@link Pattern} from the given regular expression string. In case 057 * of a {@link PatternSyntaxException} the exception is wrapped in a 058 * {@link CheckException} with an appropriate message containing the check name 059 * and the option name. 060 * 061 * @return the compiled {@link Pattern} or <code>null</code> if the given regex 062 * was empty 063 * @throws CheckException 064 * if a {@link PatternSyntaxException} occurs during compiling 065 */ 066 public static Pattern compilePatternFromCheckOptionRegex(String regex, String checkName, String optionName) 067 throws CheckException { 068 regex = regex.trim(); 069 if (StringUtils.isEmpty(regex)) { 070 return null; 071 } 072 try { 073 return Pattern.compile(regex, Pattern.CASE_INSENSITIVE); 074 } catch (PatternSyntaxException e) { 075 throw new CheckException("Syntax error in regular expression '" + regex + "' for option '" + optionName 076 + "' of check '" + checkName + "'", e); 077 } 078 } 079 080}