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}