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

org.semver.jardiff.DifferenceAccumulatingHandler Maven / Gradle / Ivy

/**
 * Copyright 2012-2014 Julien Eluard and contributors
 * This project includes software developed by Julien Eluard: https://github.com/jeluard/
 *
 * 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 org.semver.jardiff;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nonnull;

import org.osjava.jardiff.AbstractDiffHandler;
import org.osjava.jardiff.ClassInfo;
import org.osjava.jardiff.DiffException;
import org.osjava.jardiff.FieldInfo;
import org.osjava.jardiff.MethodInfo;
import org.semver.Delta;
import org.semver.Delta.Add;
import org.semver.Delta.Change;
import org.semver.Delta.Deprecate;
import org.semver.Delta.Difference;
import org.semver.Delta.Remove;

/**
 *
 * {@link org.osjava.jardiff.DiffHandler} implementation accumulating {@link Difference}.
 *
 */
public final class DifferenceAccumulatingHandler extends AbstractDiffHandler {
    private String currentClassName;
    private final Set includes;
    private final boolean includesAreRegExp;
    private final Set excludes;
    private final boolean excludesAreRegExp;
    private final Set differences = new HashSet();

    public DifferenceAccumulatingHandler() {
        this(Collections.emptySet(), Collections.emptySet());
    }

    public DifferenceAccumulatingHandler(@Nonnull final Set includes, @Nonnull final Set excludes) {
        this(includes, false, excludes, false);
    }
    public DifferenceAccumulatingHandler(@Nonnull final Set includes, final boolean includesAreRegExp,
                                         @Nonnull final Set excludes, final boolean excludesAreRegExp) {
        this.includes = includes;
        this.includesAreRegExp = includesAreRegExp;
        this.excludes = excludes;
        this.excludesAreRegExp = excludesAreRegExp;
    }

    public String getCurrentClassName() {
        return this.currentClassName;
    }

    @Override
    public void startDiff(final String previous, final String current) throws DiffException {
    }

    @Override
    public void endDiff() throws DiffException {
    }

    @Override
    public void startOldContents() throws DiffException {
    }

    @Override
    public void endOldContents() throws DiffException {
    }

    @Override
    public void startNewContents() throws DiffException {
    }

    @Override
    public void endNewContents() throws DiffException {
    }

    @Override
    public void contains(final ClassInfo classInfo) throws DiffException {
    }

    @Override
    public void startAdded() throws DiffException {
    }

    @Override
    public void classAdded(final ClassInfo classInfo) throws DiffException {
        if (!isClassConsidered(classInfo.getName())) {
            return;
        }

        this.differences.add(new Add(getClassName(classInfo.getName()), classInfo));
    }

    @Override
    public void fieldAdded(final FieldInfo fieldInfo) throws DiffException {
        if (!isClassConsidered(getCurrentClassName())) {
            return;
        }

        this.differences.add(new Add(getCurrentClassName(), fieldInfo));
    }

    @Override
    public void methodAdded(final MethodInfo methodInfo) throws DiffException {
        if (!isClassConsidered(getCurrentClassName())) {
            return;
        }

        this.differences.add(new Add(getCurrentClassName(), methodInfo));
    }

    @Override
    public void endAdded() throws DiffException {
    }

    @Override
    public void startChanged() throws DiffException {
    }

    @Override
    public void startClassChanged(final String className) throws DiffException {
        this.currentClassName = getClassName(className);
    }

    @Override
    public void classChanged(final ClassInfo oldClassInfo, final ClassInfo newClassInfo) throws DiffException {
        if (!isClassConsidered(oldClassInfo.getName())) {
            return;
        }

        this.differences.add(new Change(getClassName(oldClassInfo.getName()), oldClassInfo, newClassInfo));
    }

    @Override
    public void classDeprecated(final ClassInfo oldClassInfo, final ClassInfo newClassInfo) throws DiffException {
	if (!isClassConsidered(oldClassInfo.getName())) {
	    return;
	}

	this.differences.add(new Deprecate(getClassName(oldClassInfo.getName()), oldClassInfo, newClassInfo));
    }

    @Override
    public void fieldChanged(final FieldInfo oldFieldInfo, final FieldInfo newFieldInfo) throws DiffException {
        if (!isClassConsidered(getCurrentClassName())) {
            return;
        }

        this.differences.add(new Change(getCurrentClassName(), oldFieldInfo, newFieldInfo));
    }

    @Override
    public void fieldDeprecated(final FieldInfo oldFieldInfo, final FieldInfo newFieldInfo) throws DiffException {
	if (!isClassConsidered(getCurrentClassName())) {
	    return;
	}

	this.differences.add(new Deprecate(getCurrentClassName(), oldFieldInfo, newFieldInfo));
    }

    @Override
    public void methodChanged(final MethodInfo oldMethodInfo, final MethodInfo newMethodInfo) throws DiffException {
        if (!isClassConsidered(getCurrentClassName())) {
            return;
        }

        this.differences.add(new Change(getCurrentClassName(), oldMethodInfo, newMethodInfo));
    }

    @Override
    public void methodDeprecated(final MethodInfo oldMethodInfo, final MethodInfo newMethodInfo) throws DiffException {
	if (!isClassConsidered(getCurrentClassName())) {
	    return;
	}

	this.differences.add(new Deprecate(getCurrentClassName(), oldMethodInfo, newMethodInfo));
    }

    @Override
    public void endClassChanged() throws DiffException {
    }

    @Override
    public void endChanged() throws DiffException {
    }

    @Override
    public void startRemoved() throws DiffException {
    }

    @Override
    public void classRemoved(final ClassInfo classInfo) throws DiffException {
        if (!isClassConsidered(classInfo.getName())) {
            return;
        }

        this.differences.add(new Remove(getClassName(classInfo.getName()), classInfo));
    }

    @Override
    public void fieldRemoved(final FieldInfo fieldInfo) throws DiffException {
        if (!isClassConsidered(getCurrentClassName())) {
            return;
        }

        this.differences.add(new Remove(getCurrentClassName(), fieldInfo));
    }

    @Override
    public void methodRemoved(final MethodInfo methodInfo) throws DiffException {
        if (!isClassConsidered(getCurrentClassName())) {
            return;
        }

        this.differences.add(new Remove(getCurrentClassName(), methodInfo));
    }

    @Override
    public void endRemoved() throws DiffException {
    }

    /**
     *
     * Is considered a class whose package:
     * * is included
     * * is not excluded
     *
     * If includes are provided then package must be defined here.
     *
     * @return
     */
    protected boolean isClassConsidered( final String className ) {
         // Fix case where class names are reported with '.'
         final String fixedClassName = className.replace('.', '/');
         for ( String exclude : this.excludes ) {
             final Pattern excludePattern;
             if( !excludesAreRegExp ) {
                 if ( exclude.contains( "/**/" ) ) {
                     exclude = exclude.replaceAll( "/\\*\\*/", "{0,1}**/" );
                 }
                 if ( exclude.contains( "/*/" ) ) {
                     exclude = exclude.replaceAll( "/\\*/", "{0,1}*/{0,1}" );
                 }
                 excludePattern = simplifyRegularExpression( exclude, false );
             } else {
                 excludePattern = Pattern.compile( exclude );
             }
             final Matcher excludeMatcher = excludePattern.matcher( fixedClassName );

             while ( excludeMatcher.find() ) {
                  return false;
             }
         }
         if ( !this.includes.isEmpty() ) {
             for ( String include : this.includes ) {
                 final Pattern includePattern;
                 if( !includesAreRegExp ) {
                     if ( include.contains( "/**/" ) ) {
                         include = include.replaceAll( "/\\*\\*/", "{0,1}**/" );
                     }
                     if ( include.contains( "/*/" ) ) {
                         include = include.replaceAll( "/\\*/", "{0,1}*/{0,1}" );
                     }
                     includePattern = simplifyRegularExpression( include, false );
                 } else {
                     includePattern = Pattern.compile( include );
                 }
                 final Matcher includeMatcher = includePattern.matcher( fixedClassName );

                 while ( includeMatcher.find() ) {
                     return true;
                 }
              }
              return false;
          }
          return true;
      }

	  /**
      *
      * Simplifies the given regular expression by the following pattern:
* All substrings not containing "{0,1}", "*" and "?" get surrounded by "\\Q" and "\\E". Then all occurrences of * "**" are replaced by ".*", "*" with "[^/]*" and all occurrences of "?" are replaced by "." In the end a "$" will * be appended. * * @param regEx the regular expression which is in a simple form. * @return the simple regular expression converted to a normal regular expression. */ private static Pattern simplifyRegularExpression( final String regEx, final boolean caseSensitive ) { final StringBuilder strBuild = new StringBuilder(); final Pattern p = Pattern.compile( "\\{0,1\\}|\\*|\\?|[[^*^?^{^}]|^]+", Pattern.CASE_INSENSITIVE ); final Matcher m = p.matcher( regEx ); while ( m.find() ) { final String token = m.group(); if ( token.equals( "*" ) || token.equals( "?" ) ) { //$NON-NLS-1$ //$NON-NLS-2$ strBuild.append( token ); } else if ( token.equals( "{0,1}" ) ) { strBuild.append( "/" ); strBuild.append( token ); } else { // Surround all tokens that are not "*" or "?" with "\\Q" and \\E" strBuild.append( "\\Q" ).append( token ).append( "\\E" ); //$NON-NLS-1$ //$NON-NLS-2$ } } // Replace all "*" and "?" with .* and .+ strBuild.append( "$" ); String result = strBuild.toString(); result = result.replaceAll( "(?




© 2015 - 2025 Weber Informatics LLC | Privacy Policy