All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.devonfw.cobigen.javaplugin.matcher.JavaMatcher Maven / Gradle / Ivy

package com.devonfw.cobigen.javaplugin.matcher;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.devonfw.cobigen.api.exception.InvalidConfigurationException;
import com.devonfw.cobigen.api.extension.MatcherInterpreter;
import com.devonfw.cobigen.api.to.MatcherTo;
import com.devonfw.cobigen.api.to.VariableAssignmentTo;
import com.devonfw.cobigen.javaplugin.inputreader.to.PackageFolder;
import com.devonfw.cobigen.javaplugin.matcher.resolver.TriggerExpressionResolver;
import com.google.common.collect.Maps;
import com.thoughtworks.qdox.model.JavaClass;

/**
 * Matcher implementation for the Java Plugin
 */
public class JavaMatcher implements MatcherInterpreter {

    /** Logger instance */
    private static final Logger LOG = LoggerFactory.getLogger(JavaMatcher.class);

    /** Currently supported matcher types */
    private enum MatcherType {
        /** Full Qualified Name Matching */
        FQN,
        /** Package Name Matching */
        PACKAGE,
        /** Expression interpretation */
        EXPRESSION
    }

    /** Available variable types for the matcher */
    private enum VariableType {
        /** Constant variable assignment */
        CONSTANT,
        /** Regular expression group assignment */
        REGEX
    }

    @Override
    public boolean matches(MatcherTo matcher) {

        try {
            MatcherType matcherType = Enum.valueOf(MatcherType.class, matcher.getType().toUpperCase());
            switch (matcherType) {
            case FQN:
                String fqn = getFqn(matcher);
                LOG.debug("Matching input FQN {} against regex '{}'", fqn, matcher.getValue());
                return fqn != null && fqn.matches(matcher.getValue());
            case PACKAGE:
                return matcher.getTarget() instanceof PackageFolder
                    && ((PackageFolder) matcher.getTarget()).getPackageName().matches(matcher.getValue());
            case EXPRESSION:
                Object target = matcher.getTarget();
                if (target instanceof Object[]) {
                    // in this case we get the java class and the java source, so pick the right one to
                    // resolve the
                    // expression
                    if (((Object[]) target)[0] instanceof Class) {
                        target = ((Object[]) target)[0];
                    } else {
                        target = ((Object[]) target)[1];
                    }
                }
                if (target instanceof Class) {
                    TriggerExpressionResolver resolver = new TriggerExpressionResolver((Class) target);
                    return resolver.evaluateExpression(matcher.getValue());
                }
                if (target instanceof JavaClass) {
                    TriggerExpressionResolver resolver = new TriggerExpressionResolver((JavaClass) target);
                    return resolver.evaluateExpression(matcher.getValue());
                }
            }
        } catch (IllegalArgumentException e) {
            LOG.info("Matcher type '{}' not registered --> no match!", matcher.getType());
        }
        return false;
    }

    @Override
    public Map resolveVariables(MatcherTo matcher, List variableAssignments)
        throws InvalidConfigurationException {

        try {
            MatcherType matcherType = Enum.valueOf(MatcherType.class, matcher.getType().toUpperCase());
            switch (matcherType) {
            case FQN:
                String fqn = getFqn(matcher);
                return getResolvedVariables(matcherType, matcher.getValue(), fqn, variableAssignments);
            default:
                break;
            }
        } catch (IllegalArgumentException e) {
            LOG.warn("Matcher type '{}' not registered --> no match!", matcher.getType());
        }
        return Maps.newHashMap();
    }

    /**
     * Returns the full qualified name of the matchers input
     *
     * @param matcher
     *            {@link MatcherTo} to retrieve the input from
     * @return the full qualified name of the matchers input
     */
    private String getFqn(MatcherTo matcher) {

        Object target = matcher.getTarget();
        String fqn = null;
        if (target instanceof Object[]) {
            // in this case we get the java class and the java source, so it makes no differences
            target = ((Object[]) target)[0];
        }
        if (target instanceof Class) {
            fqn = ((Class) target).getCanonicalName();
        } else if (target instanceof JavaClass) {
            fqn = ((JavaClass) target).getCanonicalName();
        }
        return fqn;
    }

    /**
     * Resolves all variables for this trigger
     *
     * @param matcherType
     *            matcher type
     * @param matcherValue
     *            matcher value
     * @param stringToMatch
     *            String to match
     * @param variableAssignments
     *            variable assigments to be resolved
     * @return a {@link Map} from variable name to the resolved value
     * @throws InvalidConfigurationException
     *             if some of the matcher type and variable type combinations are not supported
     * @author mbrunnli (15.04.2013)
     */
    public Map getResolvedVariables(MatcherType matcherType, String matcherValue, String stringToMatch,
        List variableAssignments) throws InvalidConfigurationException {

        Map resolvedVariables = new HashMap<>();
        for (VariableAssignmentTo va : variableAssignments) {
            VariableType variableType = Enum.valueOf(VariableType.class, va.getType().toUpperCase());
            switch (variableType) {
            case CONSTANT:
                resolvedVariables.put(va.getVarName(), va.getValue());
                break;
            case REGEX:
                String resolvedRegexValue = resolveRegexValue(matcherType, matcherValue, stringToMatch, va);
                resolvedVariables.put(va.getVarName(), resolvedRegexValue != null ? resolvedRegexValue : "");
                break;
            }
        }
        return resolvedVariables;
    }

    /**
     * Resolves the variable assignments of type {@link VariableType#REGEX}
     *
     * @param matcherType
     *            type of the matcher
     * @param matcherValue
     *            value of the matcher
     * @param stringToMatch
     *            string to match
     * @param va
     *            {@link VariableAssignmentTo} to be resolved
     * @return the resolved variable
     * @throws InvalidConfigurationException
     *             thrown if the matcher type and matcher value does not work in combination
     * @author mbrunnli (08.04.2014)
     */
    private String resolveRegexValue(MatcherType matcherType, String matcherValue, String stringToMatch,
        VariableAssignmentTo va) throws InvalidConfigurationException {

        Pattern p = Pattern.compile(matcherValue);
        Matcher m = p.matcher(stringToMatch);

        if (m != null) {
            if (m.matches()) {
                try {
                    String value = m.group(Integer.parseInt(va.getValue()));
                    // removed a not null check (github issue #159) causing a InvalidConfigurationException
                    // thrown when value == null
                    return value;
                } catch (NumberFormatException e) {
                    LOG.error(
                        "The VariableAssignment '{}' of Matcher of type '{}' should have an integer as value"
                            + " representing a regular expression group.\nCurrent value: '{}'",
                        va.getType().toUpperCase(), matcherType.toString(), va.getValue(), e);
                    throw new InvalidConfigurationException("The VariableAssignment '" + va.getType().toUpperCase()
                        + "' of Matcher of type '" + matcherType.toString()
                        + "' should have an integer as value representing a regular expression group.\nCurrent value: '"
                        + va.getValue() + "'");
                } catch (IndexOutOfBoundsException e) {
                    LOG.error(
                        "The VariableAssignment '{}' of Matcher of type '{}' declares a regular expression"
                            + " group not in range.\nCurrent value: '{}'",
                        va.getType().toUpperCase(), matcherType.toString(), va.getValue(), e);
                    throw new InvalidConfigurationException("The VariableAssignment '" + va.getType().toUpperCase()
                        + "' of Matcher of type '" + matcherType.toString()
                        + "' declares a regular expression group not in range.\nCurrent value: '" + va.getValue()
                        + "'");
                }
            } // else should not occur as #matches(...) will be called beforehand
        } else {
            throw new InvalidConfigurationException(
                "The VariableAssignment type 'REGEX' can only be combined with matcher type 'FQN' or 'PACKAGE'");
        }
        return null; // should not occur
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy