/*
 * 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
 *
 *   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.netbeans.modules.java.testrunner;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.SourceGroupModifier;
import org.netbeans.api.project.Sources;
import org.netbeans.modules.gsf.testrunner.api.TestCreatorProvider;
import org.netbeans.modules.gsf.testrunner.plugin.RootsProvider;
import org.netbeans.modules.java.testrunner.providers.JavaRootsProvider;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.Lookup;
import org.openide.util.Utilities;

/**
 *
 * @author  Marian Petras
 */
public final class JavaUtils {

    /** */
    private final Project project;
    /** <!-- PENDING --> */
    private boolean sourceGroupsOnly = true;
    /** <!-- PENDING --> */
    private SourceGroup[] javaSourceGroups;
    /** <!-- PENDING --> */
    private Map<SourceGroup,Object[]> sourcesToTestsMap;
    /** <!-- PENDING --> */
    private Map<FileObject,Object> foldersToSourceGroupsMap;
    /**
     * Since 8.1, "junit" library definition and junit-3.8.2 binaries were
     * removed. This property is saved in project.properties file once the
     * project problems are resolved by updating test dependency to JUnit 4.x.
     * The possible values are "3" or "4" to indicate JUnit 3.x or JUnit 4.x
     * style for the test case sceletons.
     */
    public static final String PROP_JUNIT_SELECTED_VERSION = "junit.selected.version";
    
    /**
     * <!-- PENDING -->
     */
    public JavaUtils(Project project) {
        this.project = project;
    }
    
    /**
     * Check whether this implementation supports given FileObjects.
     *
     * @param activatedFOs FileObjects to check
     * @return {@code true} if this instance supports given FileObjects, {@code false} otherwise
     */
    public static boolean isSupportEnabled(Class lookupClass, FileObject[] activatedFOs) {
        if (activatedFOs.length == 0) {
            return false;
        }

        final FileObject firstFile = activatedFOs[0];
        Project p = FileOwnerQuery.getOwner(firstFile);
        if (p == null) {
            return false;
        }
        if(p.getLookup().lookup(lookupClass) == null) {
            return false;
        }
        
        final SourceGroup sourceGroup = findSourceGroup(firstFile);
        if (sourceGroup == null) {
            return false;
        }
        final FileObject rootFolder = sourceGroup.getRootFolder();
        if (UnitTestForSourceQuery.findUnitTests(rootFolder).length == 0) {
            return false;
        }

        /*
         * Now we know that source folder of the first file has a corresponding
         * test folder (possible non-existent).
         */
        if (activatedFOs.length == 1) {
            /* ... if there is just one file selected, it is all we need: */
            return true;
        }

        /*
         * ...for multiple files, we just check that all the selected files
         * have the same root folder:
         */
        for (int i = 1; i < activatedFOs.length; i++) {
            FileObject fileObj = activatedFOs[i];
            if (!FileUtil.isParentOf(rootFolder, fileObj)
                    || !sourceGroup.contains(fileObj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Finds a Java source group the given file belongs to.
     * 
     * @param  file  {@literal FileObject} to find a {@literal SourceGroup} for
     * @return  the found {@literal SourceGroup}, or {@literal null} if the given
     *          file does not belong to any Java source group
     */
    private static SourceGroup findSourceGroup(FileObject file) {
        final Project project = FileOwnerQuery.getOwner(file);
        if (project == null) {
            return null;
        }

        Sources src = ProjectUtils.getSources(project);
        SourceGroup[] srcGrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        for (SourceGroup srcGrp : srcGrps) {
            FileObject rootFolder = srcGrp.getRootFolder();
            if (((file == rootFolder) || FileUtil.isParentOf(rootFolder, file)) 
                    && srcGrp.contains(file)) {
                return srcGrp;
            }
        }
        return null;
    }
    
    /**
     * Finds <code>SourceGroup</code>s where a test for the given class
     * can be created (so that it can be found by the projects infrastructure
     * when a test for the class is to be opened or run).
     *
     * @param fo <code>FileObject</code> to find Source and Test filenames for
     * @param isTestNG {@code true} if user wants to create TestNG test, {@code false} otherwise
     * @param isSelenium {@code true} if user wants to create Selenium test, {@code false} otherwise
     * @return  an array of Strings - the first one being the source class name
     *          and the second being the test class name.
     *          the returned array may be empty but not <code>null</code>
     */
    public static String[] getSourceAndTestClassNames(FileObject fo, boolean isTestNG, boolean isSelenium) {
        String[] result = {"", ""};
        ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
        if (cp != null) {
            result[0] = cp.getResourceName(fo, '.', false);
            String suffix = "";
            if(isTestNG) {
                suffix = TestCreatorProvider.TESTNG_TEST_CLASS_SUFFIX;
            }
            if(isSelenium) {
                suffix = TestCreatorProvider.INTEGRATION_TEST_CLASS_SUFFIX;
            } else {
                suffix = suffix.concat(TestCreatorProvider.TEST_CLASS_SUFFIX);
            }
            result[1] = result[0].concat(suffix);
        }
        return result;
    }

    /**
     * Finds <code>SourceGroup</code>s where a test for the given class
     * can be created (so that it can be found by the projects infrastructure
     * when a test for the class is to be opened or run).
     *
     * @param createdSourceRoots
     * @param  fileObject  <code>FileObject</code> to find target
     *                     <code>SourceGroup</code>(s) for
     * @return  an array of objects - each of them can be either
     *          a <code>SourceGroup</code> for a possible target folder
     *          or simply a <code>FileObject</code> representing a possible
     *          target folder (if <code>SourceGroup</code>) for the folder
     *          was not found);
     *          the returned array may be empty but not <code>null</code>
     */
    public static Object[] getTestSourceRoots(Collection<SourceGroup> createdSourceRoots, FileObject fileObject) {
        Object[] targetFolders = CommonTestUtil.getTestTargets(fileObject);
        if (targetFolders == null || targetFolders.length == 0) {
            Project owner = FileOwnerQuery.getOwner(fileObject);
            if (owner != null) {
                String type = "";
                String hint = "";
                Collection<? extends RootsProvider> rootProviders = Lookup.getDefault().lookupAll(RootsProvider.class);
                for (RootsProvider rootProvider : rootProviders) {
                    if(rootProvider instanceof JavaRootsProvider) {
                        type = rootProvider.getSourceRootType();
                        hint = rootProvider.getProjectTestsHint();
                    }
                }
                final SourceGroup grp = SourceGroupModifier.createAssociatedSourceGroup(owner, findSourceGroup(fileObject), type, hint);
                if (grp != null) {
                    createdSourceRoots.add(grp);
                    targetFolders = CommonTestUtil.getTestTargets(fileObject);
                }
            }
        }
        return targetFolders;
    }
    
    /** <!-- PENDING --> */
    static FileObject findTestsRoot(Project project) {
        final SourceGroup[] sourceGroups
                = new JavaUtils(project).getJavaSourceGroups();
        for (int i = 0; i < sourceGroups.length; i++) {
            FileObject root = sourceGroups[i].getRootFolder();
            if (root.getName().equals(JavaProjectConstants.SOURCES_TYPE_JAVA)) {
                return root;
            }
        }
        return null;
    }
    
    /** */
    static FileObject getPackageFolder(
            FileObject root,
            String pkgName) throws IOException {
        String relativePathName = pkgName.replace('.', '/');
        FileObject folder = root.getFileObject(relativePathName);
        if (folder == null) {
            folder = FileUtil.createFolder(root, relativePathName);
        }
        return folder;
    }
    
    /**
     * Identifies and collects <code>SourceGroup</code>s and folders
     * of a given project which may serve as target folders for newly created
     * test classes.
     *
     * @param  project  project whose folders are to be checked
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
     *                           - ignore target folders not having
     *                           a corresponding <code>SourceGroup</code>
     * @return  collection which may contain <code>FileObject</code>s
     *          or <code>SourceGroup</code>s (or both);
     *          it may be empty but not <code>null</code>
     * @author  Marian Petras
     */
    static Collection getTestTargets(Project project,
                                     final boolean sourceGroupsOnly) {
        final JavaUtils utils = new JavaUtils(project);
        return utils.getTestTargets(sourceGroupsOnly);
    }

    /**
     * Identifies and collects root test folders of a given project.
     * 
     * @param  project  project whose test folders are to be found
     * @return  collection of found {@code FileObject}s, possibly empty
     *          (but not {@code null})
     */
    public static Collection<FileObject> getTestFolders(Project project) {
        return new JavaUtils(project).getTestFolders();
    }
    
    /**
     * Builds a map that containing relation between <code>SourceGroup</code>s
     * and their respective test <code>SourceGroup</code>s.
     * Each entry of the map contains a <code>SourceGroup</code> as a key
     * and an array of test <code>SourceGroup</code>s returned by
     * <code>UnitTestForSourceQuery</code> for that <code>SourceGroup</code>
     * as a value. <code>SourceGroup</code>s that have no test
     * <code>SourceGroup</code>s assigned are omitted, i.e. the resulting
     * map does not contain entries that would have empty arrays as their
     * values.
     *
     * @param  project  project whose <code>SourceGroup</code>s are to be
     *                  checked
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
     *                           - ignore test folders not having
     *                           a corresponding <code>SourceGroup</code>
     * @return  created map - may be empty, may be unmodifiable
     *                        never <code>null</code>
     */
    static Map getSourcesToTestsMap(Project project,
                                    final boolean sourceGroupsOnly) {
        final JavaUtils utils = new JavaUtils(project);
        return utils.getSourcesToTestsMap(sourceGroupsOnly);
    }
    
    /**
     * <!-- PENDING -->
     */
    Project getProject() {
        return project;
    }

    /**
     * Identifies and collects root test folders of the project.
     * 
     * @return  collection of found {@code FileObject}s
     *          - may be empty but never {@code null}
     */
    private Collection<FileObject> getTestFolders() {
        
        /*
         * Idea:
         * 1) Get all SourceGroups
         * 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
         *    test SourceGroups
         */

        /* .) get all SourceGroups: */
        final SourceGroup[] sourceGroups = getJavaSourceGroups();
        if (sourceGroups.length == 0) {
            return Collections.<FileObject>emptyList();
        }

        List<FileObject> result = null;

        /* .) for each SourceGroup, ask for test root folders: */
        for (SourceGroup sourceGroup : sourceGroups) {
            FileObject srcFolder = sourceGroup.getRootFolder();
            FileObject[] tstFoldersRaw = getTestFoldersRaw(srcFolder);
            if (tstFoldersRaw.length == 0) {
                continue;
            }

            for (FileObject tstFolder : tstFoldersRaw) {
                if (tstFolder == null) {
                    continue;
                }

                if (result == null) {
                    result = new ArrayList<FileObject>(2);
                }
                if (!result.contains(tstFolder)) {
                    result.add(tstFolder);
                }
            }
        }

        /* .) pack the results: */
        if (result == null) {
            return Collections.<FileObject>emptyList();
        } else {
            assert !result.isEmpty();
            return (result.size() == 1)
                   ? Collections.<FileObject>singleton(result.get(0))
                   : result;
        }
    }

    /**
     * Identifies and collects <code>SourceGroup</code>s and folders
     * which may serve as target folders for newly created test classes.
     *
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
     *                           (skip target folders without matching
     *                           <code>SourceGroup</code>)
     * @return  collection which may contain <code>FileObject</code>s
     *          or <code>SourceGroup</code>s (or both);
     *          it may be empty but not <code>null</code>
     * @see  #getTestTargets(Project, boolean)
     * @author  Marian Petras
     */
    private Collection<Object> getTestTargets(final boolean sourceGroupsOnly) {

        /*
         * Idea:
         * 1) Get all SourceGroups
         * 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
         *    test SourceGroups
         *
         * Union of all SourceGroups returned by UnitTestForSourceQuery
         * are the test SourceGroups.
         */

        /* .) get all SourceGroups: */
        final SourceGroup[] sourceGroups = getJavaSourceGroups();
        if (sourceGroups.length == 0) {
            return Collections.<Object>emptyList();
        }

        /* .) */
        createFoldersToSourceGroupsMap(sourceGroups);
        Object testTargetsUnion[] = new Object[sourceGroups.length];
        int size = 0;
        for (int i = 0; i < sourceGroups.length; i++) {
            Object[] testTargets = getTestTargets(sourceGroups[i],
                                                  sourceGroupsOnly);
            size = merge(testTargets, testTargetsUnion, size);
        }

        if (size != testTargetsUnion.length) {
            testTargetsUnion = CommonTestUtil.skipNulls(testTargetsUnion, new Object[0]);
        }

        return Collections.unmodifiableCollection(
                      Arrays.asList(testTargetsUnion));
    }
    
    /**
     * <!-- PENDING -->
     */
    Map<SourceGroup,Object[]> getSourcesToTestsMap() {
        if (sourcesToTestsMap == null) {
            sourcesToTestsMap = createSourcesToTestsMap(sourceGroupsOnly);
        }
        return sourcesToTestsMap;
    }
    
    /**
     * <!-- PENDING -->
     */
    Map<SourceGroup,Object[]> getSourcesToTestsMap(final boolean sourceGroupsOnly) {
        if (sourceGroupsOnly != this.sourceGroupsOnly) {
            sourcesToTestsMap = null;
            this.sourceGroupsOnly = sourceGroupsOnly;
        }
        return getSourcesToTestsMap();
    }

    /**
     * Builds a map that containing relation between <code>SourceGroup</code>s
     * and their respective test <code>SourceGroup</code>s.
     * Each entry of the map contains a <code>SourceGroup</code> as a key
     * and an array of test <code>SourceGroup</code>s returned by
     * <code>UnitTestForSourceQuery</code> for that <code>SourceGroup</code>
     * as a value. <code>SourceGroup</code>s that have no test
     * <code>SourceGroup</code>s assigned are omitted, i.e. the resulting
     * map does not contain entries that would have empty arrays as their
     * values.
     *
     * @param  sourceGroupsOnly  return only <code>SourceGroup</code>s
     *                           - ignore test folders not having
     *                           a corresponding <code>SourceGroup</code>
     * @return  created map - may be empty, may be unmodifiable,
     *                        cannot be <code>null</code>
     */
    private Map<SourceGroup,Object[]> createSourcesToTestsMap(final boolean sourceGroupsOnly) {
        
        /*
         * Idea:
         * 1) Get all SourceGroups
         * 2) For each SourceGroup, ask UnitTestForSourceQuery for its related
         *    test SourceGroups
         */

        /* .) get all SourceGroups: */
        final SourceGroup[] sourceGroups = getJavaSourceGroups();
        if (sourceGroups.length == 0) {
            return Collections.<SourceGroup,Object[]>emptyMap();
        }

        /* .) get test SourceGroups for each SourceGroup: */
        createFoldersToSourceGroupsMap(sourceGroups);
        Object testTargetsUnion[] = new Object[sourceGroups.length];
        Map<SourceGroup,Object[]> map;
        map = new HashMap<SourceGroup,Object[]>(
                            (int) ((float) sourceGroups.length * 1.33f + 0.5f),
                            .75f);
        for (int i = 0; i < sourceGroups.length; i++) {
            Object[] testTargets = getTestTargets(sourceGroups[i],
                                                  sourceGroupsOnly);
            if (testTargets.length != 0) {
                map.put(sourceGroups[i], testTargets);
            }
        }
        if (map.isEmpty()) {
            return Collections.<SourceGroup,Object[]>emptyMap();
        }
        if (map.size() == 1) {
            Map.Entry<SourceGroup,Object[]> entry
                    = map.entrySet().iterator().next();
            return Collections.singletonMap(entry.getKey(), entry.getValue());
        }

        final int finalMapSize = map.size();
        if (finalMapSize >= (sourceGroups.length - 5)) {
            return map;
        }
        
        final Map<SourceGroup,Object[]> targetMap;
        targetMap = new HashMap<SourceGroup,Object[]>(
                                    (int) ((float) finalMapSize * 1.25f + .5f),
                                    .8f);
        targetMap.putAll(map);
        return targetMap;
    }

    /**
     * Merges a given set of <code>FileObject</code>s and
     * <code>SourceGroup</code>s to the given target set (which may contain
     * same types of elements).
     * The source set (array) is not modified during merge. The target
     * set (array) is not modified otherwise than by adding (overwriting
     * <code>null</code>s) elements from the source set or by replacing elements
     * with equivalent elements (i.e. pointing to the same folder). Elements are
     * always added after the last non-<code>null</code> element of the target
     * set. After the merge, it is guaranteed that all <code>null</code>
     * elements of the target array are located at the end. The above
     * constraints can only be fulfilled if parameter
     * <code>currTargetSetSize</code> is correct and if all <code>null</code>
     * elements of the target set are placed at the end of the array at the
     * moment this method is called. The target array must contain enough
     * <code>null</code> elements so that all elements to be added to the set
     * can fit.
     *
     * @param  setToAdd  elements to be added to the target set
     *                   - must not contain <code>null</code> elements
     * @param  targetSet  array to add elements to
     * @param  currTargetSetSize  current count of non-null elements in the
     *                            target set (<code>null</code> elements are
     *                            always at the end of the array)
     * @return  new size of the target set
     *          (number of non-<code>null</code> elements)
     */
    private static int merge(final Object[] setToAdd,
                             final Object[] targetSet,
                             final int currTargetSetSize) {
        if (setToAdd.length == 0) {
            return currTargetSetSize;
        }
        if (currTargetSetSize == 0) {
            System.arraycopy(setToAdd, 0, targetSet, 0, setToAdd.length);
            return setToAdd.length;
        }
        int targetSetSize = currTargetSetSize;
        toAdd:
        for (int i = 0; i < setToAdd.length; i++) {
            final Object objToAdd = setToAdd[i];
            for (int j = 0; j < targetSetSize; j++) {
                final Object chosen = chooseTarget(targetSet[j], objToAdd);
                if (chosen != null) {           //both point to the same folder
                    targetSet[j] = chosen;
                    continue toAdd;
                }
            }
            targetSet[targetSetSize++] = objToAdd;
        }
        return targetSetSize;
    }

    /**
     * Finds whether the given two objects defining a target folder are equal
     * or not and if so, suggests which one is preferred.
     * Each of the folder targets may be either a <code>SourceGroup<code>
     * object or a <code>FileObject</code> folder. If both targets point
     * to the same folder, one of them which is preferred is returned.
     * Otherwise <code>null</code> is returned.
     * <p>
     * If both targets are <code>SourceGroup</code>s, the first target is used.
     * If none of the targets is a <code>SourceGroup</code>, the first target is
     * used.
     * Otherwise (i.e. one target is a <code>SourceGroup</code>,
     * the other is not), the <code>SourceGroup</code> target is returned.
     *
     * @param  target1  one target
     * @param  target2  second target
     * @return  <code>null</code> if the two targets define different folders;
     *          or the preferred one (of the passed targets) if the two
     *          are equal
     */
    private static Object chooseTarget(Object target1, Object target2) {
        final boolean isGroup1 = target1 instanceof SourceGroup;
        final boolean isGroup2 = target2 instanceof SourceGroup;

        assert isGroup1 || (target1 instanceof FileObject);
        assert isGroup2 || (target2 instanceof FileObject);
        
        if (isGroup1 && isGroup2 && target1.equals(target2)) {
            return target1;
        }

        final FileObject folder1 = isGroup1
                                   ? ((SourceGroup) target1).getRootFolder()
                                   : ((FileObject) target1);
        final FileObject folder2 = isGroup2
                                   ? ((SourceGroup) target2).getRootFolder()
                                   : ((FileObject) target2);
        if (!(folder1.isFolder())) {
            throw new IllegalArgumentException("target1: not a folder");//NOI18N
        }
        if (!(folder2.isFolder())) {
            throw new IllegalArgumentException("target2: not a folder");//NOI18N
        }
        if (folder1.equals(folder2)) {
            return (isGroup1 == isGroup2) ? target1
                                          : (isGroup1 ? target1 : target2);
        }
        return null;
    }

    /**
     * Returns test targets for the given <code>SourceGroup</code>.
     * The test targets are folders which are searched when tests for a class
     * from the <code>SourceGroup</code> are to be found. Each of the returned
     * test targets may be either <code>SourceGroup</code> (representing
     * a folder plus additional information such as display name) or simply
     * a <code>FileObject</code> representing a folder.
     * If parameter <code>includeSourceGroups</code> is <code>false</code>,
     * only <code>SourceGroup<code>s are returned (target folders without
     * corresponding <code>SourceGroup</code>s are ignored).
     *
     * @param  src  source group to find test targets for
     * @param  sourceGroupsOnly  skip target folders without matching
     *                           <code>SourceGroup</code>
     * @return  array which may contain <code>FileObject</code>s
     *          or <code>SourceGroup</code>s (or both);
     *          it may be empty but not <code>null</code>
     * @see  CommonTestUtil#getFileObject2SourceGroupMap
     */
    public Object[] getTestTargets(SourceGroup sourceGroup,
                                   final boolean sourceGroupsOnly) {
        
        /* .) find test root folders: */
        final FileObject[] testFolders
                    = getTestFoldersRaw(sourceGroup.getRootFolder());
        
        if (testFolders.length == 0) {
            return new Object[0];
        }
        
        /* .) find SourceGroups corresponding to the FileObjects: */
        final Object[] targets = new Object[testFolders.length];
        for (int i = 0; i < targets.length; i++) {
            final FileObject testFolder = testFolders[i];
            if (testFolder == null) {
                continue;
            }
            Object srcGroup = foldersToSourceGroupsMap.get(testFolder);
            targets[i] = (srcGroup != null)
                         ? srcGroup
                         : sourceGroupsOnly ? null : testFolder;
        }
        return CommonTestUtil.skipNulls(targets, new Object[0]);
    }
    
    /**
     * Returns an array of test folders corresponding to the given source
     * folder - may contain <code>null</code>s.
     *
     * @param  srcFolder  <code>FileObject</code> representing source code root,
     *                    for which test root folders should be found
     * @return  array of <code>FileObject</code>s representing test root
     *          folders, possibly with superfluous <code>null</code> elements
     * @see  #getSourceFoldersRaw
     */
    public FileObject[] getTestFoldersRaw(FileObject srcFolder) {
        return getFileObjects(UnitTestForSourceQuery.findUnitTests(srcFolder), true);
    }
    
    /**
     * Returns an array of source folders corresponding to the given test
     * folder - may contain <code>null</code>s.
     *
     * @param  srcFolder  <code>FileObject</code> representing source code root,
     *                    for which source root folders should be found
     * @return  array of <code>FileObject</code>s representing source root
     *          folders, possibly with superfluous <code>null</code> elements
     * @see  #getTestFoldersRaw
     */
    public FileObject[] getSourceFoldersRaw(FileObject testFolder) {
        return getFileObjects(UnitTestForSourceQuery.findSources(testFolder), true);
    }
    
    /**
     * Returns <code>FileObject</code>s represented by the given URLs.
     *
     * @param  rootURLs  URLs representing <code>FileObject</code>s
     * @param  srcToTest  <code>true</code> if we are searching for test
     *                    folders, <code>false</code> if we are searching
     *                    for source folders - affects only text of warning
     *                    log messages
     * @return  array of <code>FileObject</code>s representing source root
     *          folders, possibly with superfluous <code>null</code> elements
     */
    private FileObject[] getFileObjects(final URL[] rootURLs,
                                        final boolean srcToTest) {
        if (rootURLs.length == 0) {
            return new FileObject[0];
        }
        
        FileObject[] sourceRoots = new FileObject[rootURLs.length];
        for (int i = 0; i < rootURLs.length; i++) {
            if ((sourceRoots[i] = URLMapper.findFileObject(rootURLs[i]))
                    == null) {
                final int severity = ErrorManager.INFORMATIONAL;
                if (ErrorManager.getDefault().isLoggable(severity)) {
                    ErrorManager.getDefault().log(
                            severity,
                            (srcToTest ? "Test" : "Source")             //NOI18N
                            + " directory " + rootURLs[i]               //NOI18N
                            + " declared by project "                   //NOI18N
                            + ProjectUtils.getInformation(project).getName()
                            + " does not exist.");                      //NOI18N
                }
                continue;
            }
            Project sourceRootOwner = FileOwnerQuery.getOwner(sourceRoots[i]);
            if (!project.equals(sourceRootOwner)) {
                sourceRoots[i] = null;
                
                int severity = ErrorManager.INFORMATIONAL;
                if (ErrorManager.getDefault().isNotifiable(severity)) {
                    ErrorManager.getDefault().notify(
                        severity,
                        new IllegalStateException(
                            "Malformed project: Found test root (" +    //NOI18N
                                rootURLs[i] + ')' + ' ' +
                                (sourceRootOwner == null
                                        ? "does not belong to any"      //NOI18N
                                        : "belongs to a different") +   //NOI18N
                                " project."));                          //NOI18N
                }
                continue;
            }
        }
        return sourceRoots;
    }

    /**
     */
    public static FileObject[] skipNulls(final FileObject[] fileObjs) {
        if (fileObjs.length == 0) {
            return fileObjs;
        }
        
        int nullsCount = 0;
        for (int i = 0; i < fileObjs.length; i++) {
            if (fileObjs[i] == null) {
                nullsCount++;
            }
        }
        
        if (nullsCount == 0) {
            return fileObjs;
        }
        if (nullsCount == fileObjs.length) {
            return new FileObject[0];
        }
        
        final FileObject[] fileObjsNew
                = new FileObject[fileObjs.length - nullsCount];
        int index = 0, indexNew = 0;
        while (indexNew < fileObjsNew.length) {
            FileObject fileObj = fileObjs[index++];
            if (fileObj != null) {
                fileObjsNew[indexNew++] = fileObj;
            }
        }
        return fileObjsNew;
    }

    /**
     * Creates a map mapping folders to source groups.
     * For a folder as a key, the map returns the source group having that
     * folder as a root. The created map is stored to variable
     * {@link #foldersToSourceGroupsMap}.
     *
     * @param  sourceGroup  source group to create a map from
     * @author  Marian Petras
     */
    private void createFoldersToSourceGroupsMap(
            final SourceGroup[] sourceGroups) {
        Map<FileObject,Object> result;

        if (sourceGroups.length == 0) {
            result = Collections.<FileObject,Object>emptyMap();
        } else {
            result = new HashMap<FileObject,Object>(2 * sourceGroups.length,
                                                    .5f);
            for (SourceGroup sourceGroup : sourceGroups) {
                result.put(sourceGroup.getRootFolder(), sourceGroup);
            }
        }

        foldersToSourceGroupsMap = result;
    }
    
    /**
     * <!-- PENDING -->
     */
    public SourceGroup[] getJavaSourceGroups() {
        if (javaSourceGroups == null) {
//            String type = "";
//            Collection<? extends RootsProvider> providers = Lookup.getDefault().lookupAll(RootsProvider.class);
//            for (RootsProvider provider : providers) {
//                type = provider.getSourceRootType();
//                break;
//            }
            javaSourceGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        }
        return javaSourceGroups;
    }
    
    /**
     * Finds a <code>SourceGroup</code> having the specified root folder.
     * If there are more <code>SourceGroup</code>s matching, the first one
     * (according to the order of elements in the array) is returned.
     *
     * @param  sourceGroups  source groups to test
     * @param  rootFolder  root folder of a source group to be found
     * @return  the found <code>SourceGroup</code>;
     *          or <code>null</code> if no matching <code>SourceGroup</code>
     *          was found
     */
    private static SourceGroup findSourceGroup(SourceGroup[] sourceGroups,
                                               FileObject rootFolder) {
        for (int i = 0; i < sourceGroups.length; i++) {
            if (sourceGroups[i].getRootFolder().equals(rootFolder)) {
                return sourceGroups[i];
            }
        }
        return (SourceGroup) null;
    }
    
    static boolean isValidClassName(String className) {
        if (className.length() == 0) {
            return false;
        }
        char[] chars = className.toCharArray();
        int segmentStart = 0;
        int i;
        for (i = 0; i < chars.length; i++) {
            if (chars[i] == '.') {
                if (i == segmentStart) {
                    return false;         //empty segment
                }
                if (!Utilities.isJavaIdentifier(
                        className.substring(segmentStart, i))) {
                    return false;         //illegal name of the segment
                }
                segmentStart = i + 1;
            }
        }
        if (i == segmentStart) {
            return false;                 //empty last segment
        }
        if (!Utilities.isJavaIdentifier(
                className.substring(segmentStart, chars.length))) {
            return false;                 //illegal name of the last segment
        }
        return true;
    }
        
}
