// Path: src/main/java/hudson/plugins/scm_sync_configuration/JenkinsFilesHelper.java
// public class JenkinsFilesHelper {
// 
//     public static String buildPathRelativeToHudsonRoot(File file) {
//         File jenkinsRoot = Jenkins.getInstance().getRootDir();
//         String jenkinsRootPath = jenkinsRoot.getAbsolutePath();
//         String fileAbsolutePath = file.getAbsolutePath();
//         if (fileAbsolutePath.equals(jenkinsRootPath)) {
//             // Hmmm. Should never occur.
//             throw new IllegalArgumentException("Cannot build relative path to $JENKINS_HOME for $JENKINS_HOME itself; would be empty.");
//         }
//         if (!jenkinsRootPath.endsWith(File.separator)) {
//             jenkinsRootPath += File.separator;
//         }
//         if (!fileAbsolutePath.startsWith(jenkinsRootPath)) {
//             // Oops, the file is not relative to $JENKINS_HOME
//             return null;
//         }
//         String truncatedPath = fileAbsolutePath.substring(jenkinsRootPath.length());
//         return truncatedPath.replace(File.separatorChar, '/');
//     }
// 
//     public static File buildFileFromPathRelativeToHudsonRoot(String pathRelativeToJenkinsRoot){
//         return new File(Jenkins.getInstance().getRootDir(), pathRelativeToJenkinsRoot);
//     }
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/model/MessageWeight.java
// public enum MessageWeight {
//     MINIMAL,
//     NORMAL,
//     IMPORTANT,
//     MORE_IMPORTANT;
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/model/WeightedMessage.java
// public class WeightedMessage {
// 
//     private final String message;
//     private final MessageWeight weight;
// 
//     public WeightedMessage(String message, MessageWeight weight) {
//         this.message = message;
//         this.weight = weight;
//     }
// 
//     public String getMessage() {
//         return message;
//     }
// 
//     public MessageWeight getWeight() {
//         return weight;
//     }
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/ConfigurationEntityMatcher.java
// public interface ConfigurationEntityMatcher {
// 
//     /**
//      * Determines whether the matcher matches a given combination of saveable and file.
//      * 
//      * @param saveable the file belongs to
//      * @param file that is to be matched
//      * @return {@code true} on match, {@code false} otherwise
//      */
//     public boolean matches(Saveable saveable, File file);
// 
//     /**
//      * Determines whether the matcher would have matched a deleted file, of which we know only its path and possibly whether it was directory.
//      * 
//      * @param saveable the file belonged to
//      * @param pathRelativeToRoot of the file or directory (which Jenkins has already deleted)
//      * @param isDirectory {@code true} if it's known that the path referred to a directory, {@code false} otherwise
//      * @return {@code true} on match, {@code false} otherwise
//      */
//     public boolean matches(Saveable saveable, String pathRelativeToRoot, boolean isDirectory);
// 
//     /**
//      * Collects all files under the given rootDirectory that match, restricted by the given {@code link FileSelector}.
//      * 
//      * @param rootDirectory to traverse
//      * @param selector restricting the traversal
//      * @return an array of all path names relative to the rootDirectory of all files that match.
//      */
//     public String[] matchingFilesFrom(File rootDirectory, FileSelector selector);
// 
//     /**
//      * All patterns this matcher matches; used only for informational purposes in the UI.
//      * 
//      * @return A list of explanatory messages about the pattern the matcher matches.
//      */
//     List<String> getIncludes();
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/PageMatcher.java
// public class PageMatcher {
// 
// 	private Pattern urlRegex;
// 	private String targetFormSelector;
// 	
// 	public PageMatcher(String _urlRegexStr, String _targetFormSelector){
// 		this.urlRegex = Pattern.compile(_urlRegexStr);
// 		this.targetFormSelector = _targetFormSelector;
// 	}
// 
// 	public Pattern getUrlRegex() {
// 		return urlRegex;
// 	}
// 
// 	public String getTargetFormSelector() {
// 		return targetFormSelector;
// 	}
// }


import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import hudson.XmlFile;
import hudson.model.Item;
import hudson.model.Saveable;
import hudson.plugins.scm_sync_configuration.JenkinsFilesHelper;
import hudson.plugins.scm_sync_configuration.model.MessageWeight;
import hudson.plugins.scm_sync_configuration.model.WeightedMessage;
import hudson.plugins.scm_sync_configuration.strategies.model.ConfigurationEntityMatcher;
import hudson.plugins.scm_sync_configuration.strategies.model.PageMatcher;
import javax.annotation.Nullable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.selectors.FileSelector;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jenkins.model.Jenkins;
package hudson.plugins.scm_sync_configuration.strategies;







public abstract class AbstractScmSyncStrategy implements ScmSyncStrategy {

    private static final Function<String,File> PATH_TO_FILE_IN_HUDSON = new Function<String, File>() {
        @Override
        public File apply(@Nullable String path) {
            return new File(Jenkins.getInstance().getRootDir(), path);
        }
    };

    protected static class DefaultCommitMessageFactory implements CommitMessageFactory {
        @Override
        public WeightedMessage getMessageWhenSaveableUpdated(Saveable s, XmlFile file) {
            return new WeightedMessage("Modification on configuration(s)", MessageWeight.MINIMAL);
        }
        @Override
        public WeightedMessage getMessageWhenItemRenamed(Item item, String oldPath, String newPath) {
            return new WeightedMessage("Item renamed", MessageWeight.MINIMAL);
        }
        @Override
        public WeightedMessage getMessageWhenItemDeleted(Item item) {
            return new WeightedMessage("File hierarchy deleted", MessageWeight.MINIMAL);
        }
    }

    private final ConfigurationEntityMatcher configEntityMatcher;
    private final List<PageMatcher> pageMatchers;
    private CommitMessageFactory commitMessageFactory;

// Path: src/main/java/hudson/plugins/scm_sync_configuration/JenkinsFilesHelper.java
// public class JenkinsFilesHelper {
// 
//     public static String buildPathRelativeToHudsonRoot(File file) {
//         File jenkinsRoot = Jenkins.getInstance().getRootDir();
//         String jenkinsRootPath = jenkinsRoot.getAbsolutePath();
//         String fileAbsolutePath = file.getAbsolutePath();
//         if (fileAbsolutePath.equals(jenkinsRootPath)) {
//             // Hmmm. Should never occur.
//             throw new IllegalArgumentException("Cannot build relative path to $JENKINS_HOME for $JENKINS_HOME itself; would be empty.");
//         }
//         if (!jenkinsRootPath.endsWith(File.separator)) {
//             jenkinsRootPath += File.separator;
//         }
//         if (!fileAbsolutePath.startsWith(jenkinsRootPath)) {
//             // Oops, the file is not relative to $JENKINS_HOME
//             return null;
//         }
//         String truncatedPath = fileAbsolutePath.substring(jenkinsRootPath.length());
//         return truncatedPath.replace(File.separatorChar, '/');
//     }
// 
//     public static File buildFileFromPathRelativeToHudsonRoot(String pathRelativeToJenkinsRoot){
//         return new File(Jenkins.getInstance().getRootDir(), pathRelativeToJenkinsRoot);
//     }
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/model/MessageWeight.java
// public enum MessageWeight {
//     MINIMAL,
//     NORMAL,
//     IMPORTANT,
//     MORE_IMPORTANT;
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/model/WeightedMessage.java
// public class WeightedMessage {
// 
//     private final String message;
//     private final MessageWeight weight;
// 
//     public WeightedMessage(String message, MessageWeight weight) {
//         this.message = message;
//         this.weight = weight;
//     }
// 
//     public String getMessage() {
//         return message;
//     }
// 
//     public MessageWeight getWeight() {
//         return weight;
//     }
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/ConfigurationEntityMatcher.java
// public interface ConfigurationEntityMatcher {
// 
//     /**
//      * Determines whether the matcher matches a given combination of saveable and file.
//      * 
//      * @param saveable the file belongs to
//      * @param file that is to be matched
//      * @return {@code true} on match, {@code false} otherwise
//      */
//     public boolean matches(Saveable saveable, File file);
// 
//     /**
//      * Determines whether the matcher would have matched a deleted file, of which we know only its path and possibly whether it was directory.
//      * 
//      * @param saveable the file belonged to
//      * @param pathRelativeToRoot of the file or directory (which Jenkins has already deleted)
//      * @param isDirectory {@code true} if it's known that the path referred to a directory, {@code false} otherwise
//      * @return {@code true} on match, {@code false} otherwise
//      */
//     public boolean matches(Saveable saveable, String pathRelativeToRoot, boolean isDirectory);
// 
//     /**
//      * Collects all files under the given rootDirectory that match, restricted by the given {@code link FileSelector}.
//      * 
//      * @param rootDirectory to traverse
//      * @param selector restricting the traversal
//      * @return an array of all path names relative to the rootDirectory of all files that match.
//      */
//     public String[] matchingFilesFrom(File rootDirectory, FileSelector selector);
// 
//     /**
//      * All patterns this matcher matches; used only for informational purposes in the UI.
//      * 
//      * @return A list of explanatory messages about the pattern the matcher matches.
//      */
//     List<String> getIncludes();
// }
// 
// Path: src/main/java/hudson/plugins/scm_sync_configuration/strategies/model/PageMatcher.java
// public class PageMatcher {
// 
// 	private Pattern urlRegex;
// 	private String targetFormSelector;
// 	
// 	public PageMatcher(String _urlRegexStr, String _targetFormSelector){
// 		this.urlRegex = Pattern.compile(_urlRegexStr);
// 		this.targetFormSelector = _targetFormSelector;
// 	}
// 
// 	public Pattern getUrlRegex() {
// 		return urlRegex;
// 	}
// 
// 	public String getTargetFormSelector() {
// 		return targetFormSelector;
// 	}
// }


// Path: src/main/java/hudson/plugins/scm_sync_configuration/strategies/AbstractScmSyncStrategy.java
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import hudson.XmlFile;
import hudson.model.Item;
import hudson.model.Saveable;
import hudson.plugins.scm_sync_configuration.JenkinsFilesHelper;
import hudson.plugins.scm_sync_configuration.model.MessageWeight;
import hudson.plugins.scm_sync_configuration.model.WeightedMessage;
import hudson.plugins.scm_sync_configuration.strategies.model.ConfigurationEntityMatcher;
import hudson.plugins.scm_sync_configuration.strategies.model.PageMatcher;
import javax.annotation.Nullable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.selectors.FileSelector;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jenkins.model.Jenkins;

package hudson.plugins.scm_sync_configuration.strategies;







public abstract class AbstractScmSyncStrategy implements ScmSyncStrategy {

    private static final Function<String,File> PATH_TO_FILE_IN_HUDSON = new Function<String, File>() {
        @Override
        public File apply(@Nullable String path) {
            return new File(Jenkins.getInstance().getRootDir(), path);
        }
    };

    protected static class DefaultCommitMessageFactory implements CommitMessageFactory {
        @Override
        public WeightedMessage getMessageWhenSaveableUpdated(Saveable s, XmlFile file) {
            return new WeightedMessage("Modification on configuration(s)", MessageWeight.MINIMAL);
        }
        @Override
        public WeightedMessage getMessageWhenItemRenamed(Item item, String oldPath, String newPath) {
            return new WeightedMessage("Item renamed", MessageWeight.MINIMAL);
        }
        @Override
        public WeightedMessage getMessageWhenItemDeleted(Item item) {
            return new WeightedMessage("File hierarchy deleted", MessageWeight.MINIMAL);
        }
    }

    private final ConfigurationEntityMatcher configEntityMatcher;
    private final List<PageMatcher> pageMatchers;
    private CommitMessageFactory commitMessageFactory;

    protected AbstractScmSyncStrategy(ConfigurationEntityMatcher _configEntityMatcher, List<PageMatcher> _pageMatchers){