/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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
 *
 *      https://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.apache.tools.ant.types;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Stack;
import java.util.stream.Collectors;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.selectors.AndSelector;
import org.apache.tools.ant.types.selectors.ContainsRegexpSelector;
import org.apache.tools.ant.types.selectors.ContainsSelector;
import org.apache.tools.ant.types.selectors.DateSelector;
import org.apache.tools.ant.types.selectors.DependSelector;
import org.apache.tools.ant.types.selectors.DepthSelector;
import org.apache.tools.ant.types.selectors.DifferentSelector;
import org.apache.tools.ant.types.selectors.ExecutableSelector;
import org.apache.tools.ant.types.selectors.ExtendSelector;
import org.apache.tools.ant.types.selectors.FileSelector;
import org.apache.tools.ant.types.selectors.FilenameSelector;
import org.apache.tools.ant.types.selectors.MajoritySelector;
import org.apache.tools.ant.types.selectors.NoneSelector;
import org.apache.tools.ant.types.selectors.NotSelector;
import org.apache.tools.ant.types.selectors.OrSelector;
import org.apache.tools.ant.types.selectors.OwnedBySelector;
import org.apache.tools.ant.types.selectors.PosixGroupSelector;
import org.apache.tools.ant.types.selectors.PosixPermissionsSelector;
import org.apache.tools.ant.types.selectors.PresentSelector;
import org.apache.tools.ant.types.selectors.ReadableSelector;
import org.apache.tools.ant.types.selectors.SelectSelector;
import org.apache.tools.ant.types.selectors.SelectorContainer;
import org.apache.tools.ant.types.selectors.SelectorScanner;
import org.apache.tools.ant.types.selectors.SizeSelector;
import org.apache.tools.ant.types.selectors.SymlinkSelector;
import org.apache.tools.ant.types.selectors.TypeSelector;
import org.apache.tools.ant.types.selectors.WritableSelector;
import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;

/**
 * Class that holds an implicit patternset and supports nested
 * patternsets and creates a DirectoryScanner using these patterns.
 *
 * <p>Common base class for DirSet and FileSet.</p>
 *
 */
public abstract class AbstractFileSet extends DataType
    implements Cloneable, SelectorContainer {

    private PatternSet defaultPatterns = new PatternSet();
    private List<PatternSet> additionalPatterns = new ArrayList<>();
    private List<FileSelector> selectors = new ArrayList<>();

    private File dir;
    private boolean fileAttributeUsed;
    private boolean useDefaultExcludes = true;
    private boolean caseSensitive = true;
    private boolean followSymlinks = true;
    private boolean errorOnMissingDir = true;
    private int maxLevelsOfSymlinks = DirectoryScanner.MAX_LEVELS_OF_SYMLINKS;

    /* cached DirectoryScanner instance for our own Project only */
    private DirectoryScanner directoryScanner = null;

    /**
     * Construct a new <code>AbstractFileSet</code>.
     */
    public AbstractFileSet() {
        super();
    }

    /**
     * Construct a new <code>AbstractFileSet</code>, shallowly cloned
     * from the specified <code>AbstractFileSet</code>.
     * @param fileset the <code>AbstractFileSet</code> to use as a template.
     */
    protected AbstractFileSet(AbstractFileSet fileset) {
        this.dir = fileset.dir;
        this.defaultPatterns = fileset.defaultPatterns;
        this.additionalPatterns = fileset.additionalPatterns;
        this.selectors = fileset.selectors;
        this.useDefaultExcludes = fileset.useDefaultExcludes;
        this.caseSensitive = fileset.caseSensitive;
        this.followSymlinks = fileset.followSymlinks;
        this.errorOnMissingDir = fileset.errorOnMissingDir;
        this.maxLevelsOfSymlinks = fileset.maxLevelsOfSymlinks;
        setProject(fileset.getProject());
    }

    /**
     * Makes this instance in effect a reference to another instance.
     *
     * <p>You must not set another attribute or nest elements inside
     * this element if you make it a reference.</p>
     * @param r the <code>Reference</code> to use.
     * @throws BuildException on error
     */
    @Override
    public void setRefid(Reference r) throws BuildException {
        if (dir != null || defaultPatterns.hasPatterns(getProject())) {
            throw tooManyAttributes();
        }
        if (!additionalPatterns.isEmpty()) {
            throw noChildrenAllowed();
        }
        if (!selectors.isEmpty()) {
            throw noChildrenAllowed();
        }
        super.setRefid(r);
    }

    /**
     * Sets the base-directory for this instance.
     * @param dir the directory's <code>File</code> instance.
     * @throws BuildException on error
     */
    public synchronized void setDir(File dir) throws BuildException {
        if (isReference()) {
            throw tooManyAttributes();
        }
        if (fileAttributeUsed && !getDir().equals(dir)) {
            throw dirAndFileAreMutuallyExclusive();
        }
        this.dir = dir;
        directoryScanner = null;
    }

    /**
     * Retrieves the base-directory for this instance.
     * @return <code>File</code>.
     */
    public File getDir() {
        return getDir(getProject());
    }

    /**
     * Retrieves the base-directory for this instance.
     * @param p the <code>Project</code> against which the
     *          reference is resolved, if set.
     * @return <code>File</code>.
     */
    public synchronized File getDir(Project p) {
        if (isReference()) {
            return getRef(p).getDir(p);
        }
        dieOnCircularReference();
        return dir;
    }

    /**
     * Creates a nested patternset.
     * @return <code>PatternSet</code>.
     */
    public synchronized PatternSet createPatternSet() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        PatternSet patterns = new PatternSet();
        additionalPatterns.add(patterns);
        directoryScanner = null;
        return patterns;
    }

    /**
     * Add a name entry to the include list.
     * @return <code>PatternSet.NameEntry</code>.
     */
    public synchronized PatternSet.NameEntry createInclude() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        directoryScanner = null;
        return defaultPatterns.createInclude();
    }

    /**
     * Add a name entry to the include files list.
     * @return <code>PatternSet.PatternFileNameEntry</code>.
     */
    public synchronized PatternSet.NameEntry createIncludesFile() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        directoryScanner = null;
        return defaultPatterns.createIncludesFile();
    }

    /**
     * Add a name entry to the exclude list.
     * @return <code>PatternSet.NameEntry</code>.
     */
    public synchronized PatternSet.NameEntry createExclude() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        directoryScanner = null;
        return defaultPatterns.createExclude();
    }

    /**
     * Add a name entry to the excludes files list.
     * @return <code>PatternSet.PatternFileNameEntry</code>.
     */
    public synchronized PatternSet.NameEntry createExcludesFile() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        directoryScanner = null;
        return defaultPatterns.createExcludesFile();
    }

    /**
     * Creates a single file fileset.
     * @param file the single <code>File</code> included in this
     *             <code>AbstractFileSet</code>.
     */
    public synchronized void setFile(File file) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        if (fileAttributeUsed) {
            if (getDir().equals(file.getParentFile())) {
                String[] includes = defaultPatterns.getIncludePatterns(getProject());
                if (includes.length == 1 && includes[0].equals(file.getName())) {
                    // NOOP, setFile has been invoked twice with the same parameter
                    return;
                }
            }
            throw new BuildException("setFile cannot be called twice with different arguments");
        } else if (getDir() != null) {
            throw dirAndFileAreMutuallyExclusive();
        }
        setDir(file.getParentFile());
        fileAttributeUsed = true;
        createInclude().setName(file.getName());
    }

    /**
     * Appends <code>includes</code> to the current list of include
     * patterns.
     *
     * <p>Patterns may be separated by a comma or a space.</p>
     *
     * @param includes the <code>String</code> containing the include patterns.
     */
    public synchronized void setIncludes(String includes) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        defaultPatterns.setIncludes(includes);
        directoryScanner = null;
    }

    /**
     * Appends <code>includes</code> to the current list of include
     * patterns.
     *
     * @param includes array containing the include patterns.
     * @since Ant 1.7
     */
    public synchronized void appendIncludes(String[] includes) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        if (includes != null) {
            for (String include : includes) {
                defaultPatterns.createInclude().setName(include);
            }
            directoryScanner = null;
        }
    }

    /**
     * Appends <code>excludes</code> to the current list of exclude
     * patterns.
     *
     * <p>Patterns may be separated by a comma or a space.</p>
     *
     * @param excludes the <code>String</code> containing the exclude patterns.
     */
    public synchronized void setExcludes(String excludes) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        defaultPatterns.setExcludes(excludes);
        directoryScanner = null;
    }

    /**
     * Appends <code>excludes</code> to the current list of exclude
     * patterns.
     *
     * @param excludes array containing the exclude patterns.
     * @since Ant 1.7
     */
    public synchronized void appendExcludes(String[] excludes) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        if (excludes != null) {
            for (String exclude : excludes) {
                defaultPatterns.createExclude().setName(exclude);
            }
            directoryScanner = null;
        }
    }

    /**
     * Sets the <code>File</code> containing the includes patterns.
     *
     * @param incl <code>File</code> instance.
     * @throws BuildException on error
     */
    public synchronized void setIncludesfile(File incl) throws BuildException {
        if (isReference()) {
            throw tooManyAttributes();
        }
        defaultPatterns.setIncludesfile(incl);
        directoryScanner = null;
    }

    /**
     * Sets the <code>File</code> containing the excludes patterns.
     *
     * @param excl <code>File</code> instance.
     * @throws BuildException on error
     */
    public synchronized void setExcludesfile(File excl) throws BuildException {
        if (isReference()) {
            throw tooManyAttributes();
        }
        defaultPatterns.setExcludesfile(excl);
        directoryScanner = null;
    }

    /**
     * Sets whether default exclusions should be used or not.
     *
     * @param useDefaultExcludes <code>boolean</code>.
     */
    public synchronized void setDefaultexcludes(boolean useDefaultExcludes) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        this.useDefaultExcludes = useDefaultExcludes;
        directoryScanner = null;
    }

    /**
     * Whether default exclusions should be used or not.
     * @return the default exclusions value.
     * @since Ant 1.6.3
     */
    public synchronized boolean getDefaultexcludes() {
        if (isReference()) {
            return getRef(getProject()).getDefaultexcludes();
        }
        dieOnCircularReference();
        return useDefaultExcludes;
    }

    /**
     * Sets case sensitivity of the file system.
     *
     * @param caseSensitive <code>boolean</code>.
     */
    public synchronized void setCaseSensitive(boolean caseSensitive) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        this.caseSensitive = caseSensitive;
        directoryScanner = null;
    }

    /**
     * Find out if the fileset is case sensitive.
     *
     * @return <code>boolean</code> indicating whether the fileset is
     * case sensitive.
     *
     * @since Ant 1.7
     */
    public synchronized boolean isCaseSensitive() {
        if (isReference()) {
            return getRef(getProject()).isCaseSensitive();
        }
        dieOnCircularReference();
        return caseSensitive;
    }

    /**
     * Sets whether or not symbolic links should be followed.
     *
     * @param followSymlinks whether or not symbolic links should be followed.
     */
    public synchronized void setFollowSymlinks(boolean followSymlinks) {
        if (isReference()) {
            throw tooManyAttributes();
        }
        this.followSymlinks = followSymlinks;
        directoryScanner = null;
    }

    /**
     * Find out if the fileset wants to follow symbolic links.
     *
     * @return <code>boolean</code> indicating whether symbolic links
     *         should be followed.
     *
     * @since Ant 1.6
     */
    public synchronized boolean isFollowSymlinks() {
        if (isReference()) {
            return getRef(getProject()).isCaseSensitive();
        }
        dieOnCircularReference();
        return followSymlinks;
    }

    /**
     * The maximum number of times a symbolic link may be followed
     * during a scan.
     *
     * @param max int
     * @since Ant 1.8.0
     */
    public void setMaxLevelsOfSymlinks(int max) {
        maxLevelsOfSymlinks = max;
    }

    /**
     * The maximum number of times a symbolic link may be followed
     * during a scan.
     *
     * @return int
     * @since Ant 1.8.0
     */
    public int getMaxLevelsOfSymlinks() {
        return maxLevelsOfSymlinks;
    }

    /**
     * Sets whether an error is thrown if a directory does not exist.
     *
     * @param errorOnMissingDir true if missing directories cause errors,
     *                        false if not.
     */
     public void setErrorOnMissingDir(boolean errorOnMissingDir) {
         this.errorOnMissingDir = errorOnMissingDir;
     }

    /**
     * Gets whether an error is/should be thrown if the base directory
     * does not exist.
     *
     * @return boolean
     * @since Ant 1.8.2
     */
     public boolean getErrorOnMissingDir() {
         return errorOnMissingDir;
     }

    /**
     * Returns the directory scanner needed to access the files to process.
     * @return a <code>DirectoryScanner</code> instance.
     */
    public DirectoryScanner getDirectoryScanner() {
        return getDirectoryScanner(getProject());
    }

    /**
     * Returns the directory scanner needed to access the files to process.
     * @param p the Project against which the DirectoryScanner should be configured.
     * @return a <code>DirectoryScanner</code> instance.
     */
    public DirectoryScanner getDirectoryScanner(Project p) {
        if (isReference()) {
            return getRef(p).getDirectoryScanner(p);
        }
        dieOnCircularReference();
        final DirectoryScanner ds;
        synchronized (this) {
            if (directoryScanner != null && p == getProject()) {
                ds = directoryScanner;
            } else {
                if (dir == null) {
                    throw new BuildException("No directory specified for %s.",
                        getDataTypeName());
                }
                if (!dir.exists() && errorOnMissingDir) {
                    throw new BuildException(dir.getAbsolutePath()
                                             + DirectoryScanner
                                             .DOES_NOT_EXIST_POSTFIX);
                }
                if (!dir.isDirectory() && dir.exists()) {
                    throw new BuildException("%s is not a directory.",
                        dir.getAbsolutePath());
                }
                ds = new DirectoryScanner();
                setupDirectoryScanner(ds, p);
                ds.setFollowSymlinks(followSymlinks);
                ds.setErrorOnMissingDir(errorOnMissingDir);
                ds.setMaxLevelsOfSymlinks(maxLevelsOfSymlinks);
                directoryScanner = (p == getProject()) ? ds : directoryScanner;
            }
        }
        ds.scan();
        return ds;
    }

    /**
     * Set up the specified directory scanner against this
     * AbstractFileSet's Project.
     * @param ds a <code>FileScanner</code> instance.
     */
    public void setupDirectoryScanner(FileScanner ds) {
        setupDirectoryScanner(ds, getProject());
    }

    /**
     * Set up the specified directory scanner against the specified project.
     * @param ds a <code>FileScanner</code> instance.
     * @param p an Ant <code>Project</code> instance.
     */
    public synchronized void setupDirectoryScanner(FileScanner ds, Project p) {
        if (isReference()) {
            getRef(p).setupDirectoryScanner(ds, p);
            return;
        }
        dieOnCircularReference(p);
        if (ds == null) {
            throw new IllegalArgumentException("ds cannot be null");
        }
        ds.setBasedir(dir);

        PatternSet ps = mergePatterns(p);
        p.log(getDataTypeName() + ": Setup scanner in dir " + dir
            + " with " + ps, Project.MSG_DEBUG);

        ds.setIncludes(ps.getIncludePatterns(p));
        ds.setExcludes(ps.getExcludePatterns(p));
        if (ds instanceof SelectorScanner) {
            SelectorScanner ss = (SelectorScanner) ds;
            ss.setSelectors(getSelectors(p));
        }
        if (useDefaultExcludes) {
            ds.addDefaultExcludes();
        }
        ds.setCaseSensitive(caseSensitive);
    }

    /**
     * Performs the check for circular references and returns the
     * referenced FileSet.
     * This method can be overridden together with {@link ArchiveFileSet#getRef() getRef()}
     * providing implementations containing the special support
     * for FileSet references, which can be handled by all ArchiveFileSets.
     * NB! This method must be overridden in subclasses such as FileSet and DirSet
     * to distinguish between the data types.
     * @param p the current project
     * @return the dereferenced object.
     */
    protected AbstractFileSet getRef(Project p) {
        return getCheckedRef(AbstractFileSet.class, getDataTypeName(), p);
    }

    // SelectorContainer methods

    /**
     * Indicates whether there are any selectors here.
     *
     * @return whether any selectors are in this container.
     */
    @Override
    public synchronized boolean hasSelectors() {
        if (isReference()) {
            return getRef(getProject()).hasSelectors();
        }
        dieOnCircularReference();
        return !selectors.isEmpty();
    }

    /**
     * Indicates whether there are any patterns here.
     *
     * @return whether any patterns are in this container.
     */
    public synchronized boolean hasPatterns() {
        if (isReference() && getProject() != null) {
            return getRef(getProject()).hasPatterns();
        }
        dieOnCircularReference();
        return defaultPatterns.hasPatterns(getProject())
                || additionalPatterns.stream().anyMatch(ps -> ps.hasPatterns(getProject()));
    }

    /**
     * Gives the count of the number of selectors in this container.
     *
     * @return the number of selectors in this container as an <code>int</code>.
     */
    @Override
    public synchronized int selectorCount() {
        if (isReference()) {
            return getRef(getProject()).selectorCount();
        }
        dieOnCircularReference();
        return selectors.size();
    }

    /**
     * Returns the set of selectors as an array.
     * @param p the current project
     * @return a <code>FileSelector[]</code> of the selectors in this container.
     */
    @Override
    public synchronized FileSelector[] getSelectors(Project p) {
        if (isReference()) {
            return getRef(getProject()).getSelectors(p);
        }
        dieOnCircularReference(p);
        return selectors.toArray(new FileSelector[selectors.size()]);
    }

    /**
     * Returns an enumerator for accessing the set of selectors.
     *
     * @return an <code>Enumeration</code> of selectors.
     */
    @Override
    public synchronized Enumeration<FileSelector> selectorElements() {
        if (isReference()) {
            return getRef(getProject()).selectorElements();
        }
        dieOnCircularReference();
        return Collections.enumeration(selectors);
    }

    /**
     * Add a new selector into this container.
     *
     * @param selector the new <code>FileSelector</code> to add.
     */
    @Override
    public synchronized void appendSelector(FileSelector selector) {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        selectors.add(selector);
        directoryScanner = null;
        setChecked(false);
    }

    /* Methods below all add specific selectors */

    /**
     * Add a "Select" selector entry on the selector list.
     * @param selector the <code>SelectSelector</code> to add.
     */
    @Override
    public void addSelector(SelectSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add an "And" selector entry on the selector list.
     * @param selector the <code>AndSelector</code> to add.
     */
    @Override
    public void addAnd(AndSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add an "Or" selector entry on the selector list.
     * @param selector the <code>OrSelector</code> to add.
     */
    @Override
    public void addOr(OrSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a "Not" selector entry on the selector list.
     * @param selector the <code>NotSelector</code> to add.
     */
    @Override
    public void addNot(NotSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a "None" selector entry on the selector list.
     * @param selector the <code>NoneSelector</code> to add.
     */
    @Override
    public void addNone(NoneSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a majority selector entry on the selector list.
     * @param selector the <code>MajoritySelector</code> to add.
     */
    @Override
    public void addMajority(MajoritySelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a selector date entry on the selector list.
     * @param selector the <code>DateSelector</code> to add.
     */
    @Override
    public void addDate(DateSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a selector size entry on the selector list.
     * @param selector the <code>SizeSelector</code> to add.
     */
    @Override
    public void addSize(SizeSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a DifferentSelector entry on the selector list.
     * @param selector the <code>DifferentSelector</code> to add.
     */
    @Override
    public void addDifferent(DifferentSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a selector filename entry on the selector list.
     * @param selector the <code>FilenameSelector</code> to add.
     */
    @Override
    public void addFilename(FilenameSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a selector type entry on the selector list.
     * @param selector the <code>TypeSelector</code> to add.
     */
    @Override
    public void addType(TypeSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add an extended selector entry on the selector list.
     * @param selector the <code>ExtendSelector</code> to add.
     */
    @Override
    public void addCustom(ExtendSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a contains selector entry on the selector list.
     * @param selector the <code>ContainsSelector</code> to add.
     */
    @Override
    public void addContains(ContainsSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a present selector entry on the selector list.
     * @param selector the <code>PresentSelector</code> to add.
     */
    @Override
    public void addPresent(PresentSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a depth selector entry on the selector list.
     * @param selector the <code>DepthSelector</code> to add.
     */
    @Override
    public void addDepth(DepthSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a depends selector entry on the selector list.
     * @param selector the <code>DependSelector</code> to add.
     */
    @Override
    public void addDepend(DependSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add a regular expression selector entry on the selector list.
     * @param selector the <code>ContainsRegexpSelector</code> to add.
     */
    @Override
    public void addContainsRegexp(ContainsRegexpSelector selector) {
        appendSelector(selector);
    }

    /**
     * Add the modified selector.
     * @param selector the <code>ModifiedSelector</code> to add.
     * @since Ant 1.6
     */
    @Override
    public void addModified(ModifiedSelector selector) {
        appendSelector(selector);
    }

    public void addReadable(ReadableSelector r) {
        appendSelector(r);
    }

    public void addWritable(WritableSelector w) {
        appendSelector(w);
    }

    /**
     * @param e ExecutableSelector
     * @since 1.10.0
     */
    public void addExecutable(ExecutableSelector e) {
        appendSelector(e);
    }

    /**
     * @param e SymlinkSelector
     * @since 1.10.0
     */
    public void addSymlink(SymlinkSelector e) {
        appendSelector(e);
    }

    /**
     * @param o OwnedBySelector
     * @since 1.10.0
     */
    public void addOwnedBy(OwnedBySelector o) {
        appendSelector(o);
    }

    /**
     * @param o PosixGroupSelector
     * @since 1.10.4
     */
    public void addPosixGroup(PosixGroupSelector o) {
        appendSelector(o);
    }

    /**
     * @param o PosixPermissionsSelector
     * @since 1.10.4
     */
    public void addPosixPermissions(PosixPermissionsSelector o) {
        appendSelector(o);
    }

    /**
     * Add an arbitrary selector.
     * @param selector the <code>FileSelector</code> to add.
     * @since Ant 1.6
     */
    @Override
    public void add(FileSelector selector) {
        appendSelector(selector);
    }

    /**
     * Returns included files as a list of semicolon-separated filenames.
     *
     * @return a <code>String</code> of included filenames.
     */
    @Override
    public String toString() {
        if (isReference()) {
            return getRef(getProject()).toString();
        }
        dieOnCircularReference();
        return String.join(";", getDirectoryScanner().getIncludedFiles());
    }

    /**
     * Creates a deep clone of this instance, except for the nested
     * selectors (the list of selectors is a shallow clone of this
     * instance's list).
     * @return the cloned object
     * @since Ant 1.6
     */
    @Override
    public synchronized Object clone() {
        if (isReference()) {
            return (getRef(getProject())).clone();
        }
        try {
            AbstractFileSet fs = (AbstractFileSet) super.clone();
            fs.defaultPatterns = (PatternSet) defaultPatterns.clone();
            fs.additionalPatterns = additionalPatterns.stream().map(PatternSet::clone)
                    .map(PatternSet.class::cast).collect(Collectors.toList());
            fs.selectors = new ArrayList<>(selectors);
            return fs;
        } catch (CloneNotSupportedException e) {
            throw new BuildException(e);
        }
    }

    /**
     * Get the merged include patterns for this AbstractFileSet.
     * @param p the project to use.
     * @return the include patterns of the default pattern set and all
     * nested patternsets.
     *
     * @since Ant 1.7
     */
    public String[] mergeIncludes(Project p) {
        return mergePatterns(p).getIncludePatterns(p);
    }

    /**
     * Get the merged exclude patterns for this AbstractFileSet.
     * @param p the project to use.
     * @return the exclude patterns of the default pattern set and all
     * nested patternsets.
     *
     * @since Ant 1.7
     */
    public String[] mergeExcludes(Project p) {
        return mergePatterns(p).getExcludePatterns(p);
    }

    /**
     * Get the merged patterns for this AbstractFileSet.
     * @param p the project to use.
     * @return the default patternset merged with the additional sets
     * in a new PatternSet instance.
     *
     * @since Ant 1.7
     */
    public synchronized PatternSet mergePatterns(Project p) {
        if (isReference()) {
            return getRef(p).mergePatterns(p);
        }
        dieOnCircularReference();
        PatternSet ps = (PatternSet) defaultPatterns.clone();
        additionalPatterns.forEach(pat -> ps.append(pat, p));
        return ps;
    }

    @Override
    protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
        throws BuildException {
        if (isChecked()) {
            return;
        }
        if (isReference()) {
            super.dieOnCircularReference(stk, p);
        } else {
            selectors.stream().filter(DataType.class::isInstance).map(DataType.class::cast)
                    .forEach(type -> pushAndInvokeCircularReferenceCheck(type, stk, p));
            additionalPatterns.forEach(ps -> pushAndInvokeCircularReferenceCheck(ps, stk, p));
            setChecked(true);
        }
    }

    private BuildException dirAndFileAreMutuallyExclusive() {
        return new BuildException("you can only specify one of the dir and file attributes");
    }
}
