#!/usr/bin/env python3
#
# Copyright 2018 - The Android Open Source Project
#
# 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.

"""Collect the source paths from dependency information."""

from __future__ import absolute_import

import glob
import logging
import os
import re

from aidegen import constant
from aidegen.lib import common_util
from aidegen.lib import errors
from aidegen.lib import project_config
from atest import atest_utils

# Parse package name from the package declaration line of a java.
# Group matches "foo.bar" of line "package foo.bar;" or "package foo.bar"
_PACKAGE_RE = re.compile(r'\s*package\s+(?P<package>[^(;|\s)]+)\s*', re.I)

_ANDROID_SUPPORT_PATH_KEYWORD = 'prebuilts/sdk/current/'
# File extensions
_JAR_EXT = '.jar'
_JAVA_EXT = '.java'
_KOTLIN_EXT = '.kt'
_SRCJAR_EXT = '.srcjar'

_TARGET_LIBS = [_JAR_EXT]
_TARGET_FILES = [_JAVA_EXT, _KOTLIN_EXT]
_JARJAR_RULES_FILE = 'jarjar-rules.txt'
_KEY_JARJAR_RULES = 'jarjar_rules'
_KEY_JARS = 'jars'
_KEY_TESTS = 'tests'
_NAME_AAPT2 = 'aapt2'
_TARGET_R_JAR = 'R.jar'
_TARGET_AAPT2_SRCJAR = _NAME_AAPT2 + _SRCJAR_EXT
_TARGET_BUILD_FILES = [_TARGET_AAPT2_SRCJAR, _TARGET_R_JAR]
_IGNORE_DIRS = [
    # The java files under this directory have to be ignored because it will
    # cause duplicated classes by libcore/ojluni/src/main/java.
    'libcore/ojluni/src/lambda/java'
]
_DIS_ROBO_BUILD_ENV_VAR = {'DISABLE_ROBO_RUN_TESTS': 'true'}
# When we use atest_utils.build(), there is a command length limit on
# soong_ui.bash. We reserve 5000 characters for rewriting the command line
# in soong_ui.bash.
_CMD_LENGTH_BUFFER = 5000
# For each argument, it need a space to separate following argument.
_BLANK_SIZE = 1


def multi_projects_locate_source(projects):
    """Locate the paths of dependent source folders and jar files with projects.

    Args:
        projects: A list of ProjectInfo instances. Information of a project such
                  as project relative path, project real path, project
                  dependencies.
    """
    for project in projects:
        locate_source(
            project,
            project_config.ProjectConfig.get_instance().verbose,
            project_config.ProjectConfig.get_instance().depth,
            project_config.ProjectConfig.get_instance().ide_name,
            build=not project_config.ProjectConfig.get_instance().is_skip_build)


def locate_source(project, verbose, depth, ide_name, build=True):
    """Locate the paths of dependent source folders and jar files.

    Try to reference source folder path as dependent module unless the
    dependent module should be referenced to a jar file, such as modules have
    jars and jarjar_rules parameter.
    For example:
        Module: asm-6.0
            java_import {
                name: 'asm-6.0',
                host_supported: true,
                jars: ['asm-6.0.jar'],
            }
        Module: bouncycastle
            java_library {
                name: 'bouncycastle',
                ...
                target: {
                    android: {
                        jarjar_rules: 'jarjar-rules.txt',
                    },
                },
            }

    Args:
        project: A ProjectInfo instance. Information of a project such as
                 project relative path, project real path, project dependencies.
        verbose: A boolean, if true displays full build output.
        depth: An integer shows the depth of module dependency referenced by
               source. Zero means the max module depth.
        ide_name: A string stands for the IDE name, default is IntelliJ.
        build: A boolean default to true, if true skip building jar and srcjar
               files, otherwise build them.

    Example usage:
        project.source_path = locate_source(project, verbose, False)
        E.g.
            project.source_path = {
                'source_folder_path': ['path/to/source/folder1',
                                       'path/to/source/folder2', ...],
                'test_folder_path': ['path/to/test/folder', ...],
                'jar_path': ['path/to/jar/file1', 'path/to/jar/file2', ...]
            }
    """
    if not hasattr(project, 'dep_modules') or not project.dep_modules:
        raise errors.EmptyModuleDependencyError(
            'Dependent modules dictionary is empty.')
    dependencies = project.source_path
    rebuild_targets = set()
    for module_name, module_data in project.dep_modules.items():
        module = _generate_moduledata(module_name, module_data, ide_name,
                                      project.project_relative_path, depth)
        module.locate_sources_path()
        dependencies['source_folder_path'].update(module.src_dirs)
        dependencies['test_folder_path'].update(module.test_dirs)
        dependencies['r_java_path'].update(module.r_java_paths)
        dependencies['srcjar_path'].update(module.srcjar_paths)
        _append_jars_as_dependencies(dependencies, module)
        if module.build_targets:
            rebuild_targets |= module.build_targets
    if rebuild_targets:
        if build:
            _batch_build_dependencies(verbose, rebuild_targets)
            locate_source(project, verbose, depth, ide_name, build=False)
        else:
            logging.warning('Jar or srcjar files build failed:\n\t%s.',
                            '\n\t'.join(rebuild_targets))


def _batch_build_dependencies(verbose, rebuild_targets):
    """Batch build the jar or srcjar files of the modules if they don't exist.

    Command line has the max length limit, MAX_ARG_STRLEN, and
    MAX_ARG_STRLEN = (PAGE_SIZE * 32).
    If the build command is longer than MAX_ARG_STRLEN, this function will
    separate the rebuild_targets into chunks with size less or equal to
    MAX_ARG_STRLEN to make sure it can be built successfully.

    Args:
        verbose: A boolean, if true displays full build output.
        rebuild_targets: A set of jar or srcjar files which do not exist.
    """
    logging.info('Ready to build the jar or srcjar files. Files count = %s',
                 str(len(rebuild_targets)))
    arg_max = os.sysconf("SC_PAGE_SIZE") * 32 - _CMD_LENGTH_BUFFER
    rebuild_targets = list(rebuild_targets)
    for start, end in iter(_separate_build_targets(
            rebuild_targets, arg_max)):
        _build_target(rebuild_targets[start: end], verbose)


def _build_target(targets, verbose):
    """Build the jar or srcjar files.

    Use -k to keep going when some targets can't be built or build failed.
    Use -j to speed up building.

    Args:
        targets: A list of jar or srcjar files which need to build.
        verbose: A boolean, if true displays full build output.
    """
    build_cmd = ['-k', '-j']
    build_cmd.extend(list(targets))
    if not atest_utils.build(build_cmd, verbose, _DIS_ROBO_BUILD_ENV_VAR):
        message = ('Build failed!\n{}\nAIDEGen will proceed but dependency '
                   'correctness is not guaranteed if not all targets being '
                   'built successfully.'.format('\n'.join(targets)))
        print('\n{} {}\n'.format(common_util.COLORED_INFO('Warning:'),
                                 message))


def _separate_build_targets(build_targets, max_length):
    """Separate the build_targets by limit the command size to max command
    length.

    Args:
        build_targets: A list to be separated.
        max_length: The max number of each build command length.

    Yields:
        The start index and end index of build_targets.
    """
    arg_len = 0
    first_item_index = 0
    for i, item in enumerate(build_targets):
        arg_len = arg_len + len(item) + _BLANK_SIZE
        if arg_len > max_length:
            yield first_item_index, i
            first_item_index = i
            arg_len = len(item) + _BLANK_SIZE
    if first_item_index < len(build_targets):
        yield first_item_index, len(build_targets)


def _generate_moduledata(module_name, module_data, ide_name, project_relpath,
                         depth):
    """Generate a module class to collect dependencies in IntelliJ or Eclipse.

    Args:
        module_name: Name of the module.
        module_data: A dictionary holding a module information.
        ide_name: A string stands for the IDE name.
        project_relpath: A string stands for the project's relative path.
        depth: An integer shows the depth of module dependency referenced by
               source. Zero means the max module depth.

    Returns:
        A ModuleData class.
    """
    if ide_name == constant.IDE_ECLIPSE:
        return EclipseModuleData(module_name, module_data, project_relpath)
    return ModuleData(module_name, module_data, depth)


def _append_jars_as_dependencies(dependent_data, module):
    """Add given module's jar files into dependent_data as dependencies.

    Args:
        dependent_data: A dictionary contains the dependent source paths and
                        jar files.
        module: A ModuleData instance.
    """
    if module.jar_files:
        dependent_data['jar_path'].update(module.jar_files)
        for jar in list(module.jar_files):
            dependent_data['jar_module_path'].update({jar: module.module_path})
    # Collecting the jar files of default core modules as dependencies.
    if constant.KEY_DEPENDENCIES in module.module_data:
        dependent_data['jar_path'].update([
            x for x in module.module_data[constant.KEY_DEPENDENCIES]
            if common_util.is_target(x, _TARGET_LIBS)
        ])


class ModuleData:
    """ModuleData class.

    Attributes:
        All following relative paths stand for the path relative to the android
        repo root.

        module_path: A string of the relative path to the module.
        src_dirs: A set to keep the unique source folder relative paths.
        test_dirs: A set to keep the unique test folder relative paths.
        jar_files: A set to keep the unique jar file relative paths.
        r_java_paths: A set to keep the R folder paths to use in Eclipse.
        srcjar_paths: A set to keep the srcjar source root paths to use in
                      IntelliJ.
        referenced_by_jar: A boolean to check if the module is referenced by a
                           jar file.
        build_targets: A set to keep the unique build target jar or srcjar file
                       relative paths which are ready to be rebuld.
        missing_jars: A set to keep the jar file relative paths if it doesn't
                      exist.
        specific_soong_path: A string of the relative path to the module's
                             intermediates folder under out/.
    """

    def __init__(self, module_name, module_data, depth):
        """Initialize ModuleData.

        Args:
            module_name: Name of the module.
            module_data: A dictionary holding a module information.
            depth: An integer shows the depth of module dependency referenced by
                   source. Zero means the max module depth.
            For example:
                {
                    'class': ['APPS'],
                    'path': ['path/to/the/module'],
                    'depth': 0,
                    'dependencies': ['bouncycastle', 'ims-common'],
                    'srcs': [
                        'path/to/the/module/src/com/android/test.java',
                        'path/to/the/module/src/com/google/test.java',
                        'out/soong/.intermediates/path/to/the/module/test/src/
                         com/android/test.srcjar'
                    ],
                    'installed': ['out/target/product/generic_x86_64/
                                   system/framework/framework.jar'],
                    'jars': ['settings.jar'],
                    'jarjar_rules': ['jarjar-rules.txt']
                }
        """
        assert module_name, 'Module name can\'t be null.'
        assert module_data, 'Module data of %s can\'t be null.' % module_name
        self.module_name = module_name
        self.module_data = module_data
        self._init_module_path()
        self._init_module_depth(depth)
        self.src_dirs = set()
        self.test_dirs = set()
        self.jar_files = set()
        self.r_java_paths = set()
        self.srcjar_paths = set()
        self.referenced_by_jar = False
        self.build_targets = set()
        self.missing_jars = set()
        self.specific_soong_path = os.path.join(
            'out/soong/.intermediates', self.module_path, self.module_name)

    def _is_app_module(self):
        """Check if the current module's class is APPS"""
        return self._check_key('class') and 'APPS' in self.module_data['class']

    def _is_target_module(self):
        """Check if the current module is a target module.

        A target module is the target project or a module under the
        target project and it's module depth is 0.
        For example: aidegen Settings framework
            The target projects are Settings and framework so they are also
            target modules. And the dependent module SettingsUnitTests's path
            is packages/apps/Settings/tests/unit so it also a target module.
        """
        return self.module_depth == 0

    def _collect_r_srcs_paths(self):
        """Collect the source folder of R.java.

        Check if the path of aapt2.srcjar or R.jar exists, which is the value of
        key "srcjars" in module_data. If the path of both 2 cases doesn't exist,
        build it onto an intermediates directory.

        For IntelliJ, we can set the srcjar file as a source root for
        dependency. For Eclipse, we still use the R folder as dependencies until
        we figure out how to set srcjar file as dependency.
        # TODO(b/135594800): Set aapt2.srcjar or R.jar as a dependency in
                             Eclipse.
        """
        if (self._is_app_module() and self._is_target_module() and
                self._check_key(constant.KEY_SRCJARS)):
            for srcjar in self.module_data[constant.KEY_SRCJARS]:
                if not os.path.exists(common_util.get_abs_path(srcjar)):
                    self.build_targets.add(srcjar)
                self._collect_srcjar_path(srcjar)
                r_dir = self._get_r_dir(srcjar)
                if r_dir:
                    self.r_java_paths.add(r_dir)

    def _collect_srcjar_path(self, srcjar):
        """Collect the source folders from a srcjar path.

        Set the aapt2.srcjar or R.jar as source root:
        Case aapt2.srcjar:
            The source path string is
            out/.../Bluetooth_intermediates/aapt2.srcjar
            The source content descriptor is
            out/.../Bluetooth_intermediates/aapt2.srcjar!/.
        Case R.jar:
            The source path string is out/soong/.../gen/R.jar.
            The source content descriptor is out/soong/.../gen/R.jar!/.

        Args:
            srcjar: A file path string relative to ANDROID_BUILD_TOP, the build
                    target of the module to generate R.java.
        """
        if os.path.basename(srcjar) in _TARGET_BUILD_FILES:
            self.srcjar_paths.add('%s!/' % srcjar)

    @staticmethod
    def _get_r_dir(srcjar):
        """Get the source folder of R.java for Eclipse.

        Args:
            srcjar: A file path string, the build target of the module to
                    generate R.java.

        Returns:
            A relative source folder path string, and return None if the target
            file name is not aapt2.srcjar or R.jar.
        """
        target_folder, target_file = os.path.split(srcjar)
        if target_file == _TARGET_AAPT2_SRCJAR:
            return os.path.join(target_folder, _NAME_AAPT2)
        if target_file == _TARGET_R_JAR:
            return os.path.join(target_folder, _NAME_AAPT2, 'R')
        return None

    def _init_module_path(self):
        """Inintialize self.module_path."""
        self.module_path = (self.module_data[constant.KEY_PATH][0]
                            if self._check_key(constant.KEY_PATH) else '')

    def _init_module_depth(self, depth):
        """Initialize module depth's settings.

        Set the module's depth from module info when user have -d parameter.
        Set the -d value from user input, default to 0.

        Args:
            depth: the depth to be set.
        """
        self.module_depth = (int(self.module_data[constant.KEY_DEPTH])
                             if depth else 0)
        self.depth_by_source = depth

    def _is_android_supported_module(self):
        """Determine if this is an Android supported module."""
        return self.module_path.startswith(_ANDROID_SUPPORT_PATH_KEYWORD)

    def _check_jarjar_rules_exist(self):
        """Check if jarjar rules exist."""
        return (_KEY_JARJAR_RULES in self.module_data and
                self.module_data[_KEY_JARJAR_RULES][0] == _JARJAR_RULES_FILE)

    def _check_jars_exist(self):
        """Check if jars exist."""
        return self._check_key(_KEY_JARS)

    def _check_classes_jar_exist(self):
        """Check if classes_jar exist."""
        return self._check_key(constant.KEY_CLASSES_JAR)

    def _collect_srcs_paths(self):
        """Collect source folder paths in src_dirs from module_data['srcs']."""
        if self._check_key(constant.KEY_SRCS):
            scanned_dirs = set()
            for src_item in self.module_data[constant.KEY_SRCS]:
                src_dir = None
                src_item = os.path.relpath(src_item)
                if src_item.endswith(_SRCJAR_EXT):
                    self._append_jar_from_installed(self.specific_soong_path)
                elif common_util.is_target(src_item, _TARGET_FILES):
                    # Only scan one java file in each source directories.
                    src_item_dir = os.path.dirname(src_item)
                    if src_item_dir not in scanned_dirs:
                        scanned_dirs.add(src_item_dir)
                        src_dir = self._get_source_folder(src_item)
                else:
                    # To record what files except java and srcjar in the srcs.
                    logging.debug('%s is not in parsing scope.', src_item)
                if src_dir:
                    self._add_to_source_or_test_dirs(src_dir)

    def _check_key(self, key):
        """Check if key is in self.module_data and not empty.

        Args:
            key: the key to be checked.
        """
        return key in self.module_data and self.module_data[key]

    def _add_to_source_or_test_dirs(self, src_dir):
        """Add folder to source or test directories.

        Args:
            src_dir: the directory to be added.
        """
        if not any(path in src_dir for path in _IGNORE_DIRS):
            if self._is_test_module(src_dir):
                self.test_dirs.add(src_dir)
            else:
                self.src_dirs.add(src_dir)

    @staticmethod
    def _is_test_module(src_dir):
        """Check if the module path is a test module path.

        Args:
            src_dir: the directory to be checked.

        Returns:
            True if module path is a test module path, otherwise False.
        """
        return _KEY_TESTS in src_dir.split(os.sep)

    def _get_source_folder(self, java_file):
        """Parsing a java to get the package name to filter out source path.

        Args:
            java_file: A string, the java file with relative path.
                       e.g. path/to/the/java/file.java

        Returns:
            source_folder: A string of path to source folder(e.g. src/main/java)
                           or none when it failed to get package name.
        """
        abs_java_path = common_util.get_abs_path(java_file)
        if os.path.exists(abs_java_path):
            package_name = self._get_package_name(abs_java_path)
            if package_name:
                return self._parse_source_path(java_file, package_name)
        return None

    @staticmethod
    def _parse_source_path(java_file, package_name):
        """Parse the source path by filter out the package name.

        Case 1:
        java file: a/b/c/d/e.java
        package name: c.d
        The source folder is a/b.

        Case 2:
        java file: a/b/c.d/e.java
        package name: c.d
        The source folder is a/b.

        Case 3:
        java file: a/b/c/d/e.java
        package name: x.y
        The source folder is a/b/c/d.

        Case 4:
        java file: a/b/c.d/e/c/d/f.java
        package name: c.d
        The source folder is a/b/c.d/e.

        Case 5:
        java file: a/b/c.d/e/c.d/e/f.java
        package name: c.d.e
        The source folder is a/b/c.d/e.

        Args:
            java_file: A string of the java file relative path.
            package_name: A string of the java file's package name.

        Returns:
            A string, the source folder path.
        """
        java_file_name = os.path.basename(java_file)
        pattern = r'%s/%s$' % (package_name, java_file_name)
        search_result = re.search(pattern, java_file)
        if search_result:
            return java_file[:search_result.start()].strip(os.sep)
        return os.path.dirname(java_file)

    @staticmethod
    def _get_package_name(abs_java_path):
        """Get the package name by parsing a java file.

        Args:
            abs_java_path: A string of the java file with absolute path.
                           e.g. /root/path/to/the/java/file.java

        Returns:
            package_name: A string of package name.
        """
        package_name = None
        with open(abs_java_path, encoding="utf8") as data:
            for line in data.read().splitlines():
                match = _PACKAGE_RE.match(line)
                if match:
                    package_name = match.group('package')
                    break
        return package_name

    def _append_jar_file(self, jar_path):
        """Append a path to the jar file into self.jar_files if it's exists.

        Args:
            jar_path: A path supposed to be a jar file.

        Returns:
            Boolean: True if jar_path is an existing jar file.
        """
        if common_util.is_target(jar_path, _TARGET_LIBS):
            self.referenced_by_jar = True
            if os.path.isfile(common_util.get_abs_path(jar_path)):
                self.jar_files.add(jar_path)
            else:
                self.missing_jars.add(jar_path)
            return True
        return False

    def _append_classes_jar(self):
        """Append the jar file as dependency for prebuilt modules."""
        for jar in self.module_data[constant.KEY_CLASSES_JAR]:
            if self._append_jar_file(jar):
                break

    def _append_jar_from_installed(self, specific_dir=None):
        """Append a jar file's path to the list of jar_files with matching
        path_prefix.

        There might be more than one jar in "installed" parameter and only the
        first jar file is returned. If specific_dir is set, the jar file must be
        under the specific directory or its sub-directory.

        Args:
            specific_dir: A string of path.
        """
        if self._check_key(constant.KEY_INSTALLED):
            for jar in self.module_data[constant.KEY_INSTALLED]:
                if specific_dir and not jar.startswith(specific_dir):
                    continue
                if self._append_jar_file(jar):
                    break

    def _set_jars_jarfile(self):
        """Append prebuilt jars of module into self.jar_files.

        Some modules' sources are prebuilt jar files instead of source java
        files. The jar files can be imported into IntelliJ as a dependency
        directly. There is only jar file name in self.module_data['jars'], it
        has to be combined with self.module_data['path'] to append into
        self.jar_files.
        For example:
        'asm-6.0': {
            'jars': [
                'asm-6.0.jar'
            ],
            'path': [
                'prebuilts/misc/common/asm'
            ],
        },
        Path to the jar file is prebuilts/misc/common/asm/asm-6.0.jar.
        """
        if self._check_key(_KEY_JARS):
            for jar_name in self.module_data[_KEY_JARS]:
                if self._check_key(constant.KEY_INSTALLED):
                    self._append_jar_from_installed()
                else:
                    jar_path = os.path.join(self.module_path, jar_name)
                    jar_abs = common_util.get_abs_path(jar_path)
                    if not os.path.isfile(jar_abs) and jar_name.endswith(
                            'prebuilt.jar'):
                        rel_path = self._get_jar_path_from_prebuilts(jar_name)
                        if rel_path:
                            jar_path = rel_path
                    self._append_jar_file(jar_path)

    @staticmethod
    def _get_jar_path_from_prebuilts(jar_name):
        """Get prebuilt jar file from prebuilts folder.

        If the prebuilt jar file we get from method _set_jars_jarfile() does not
        exist, we should search the prebuilt jar file in prebuilts folder.
        For example:
        'platformprotos': {
            'jars': [
                'platformprotos-prebuilt.jar'
            ],
            'path': [
                'frameworks/base'
            ],
        },
        We get an incorrect path: 'frameworks/base/platformprotos-prebuilt.jar'
        If the file does not exist, we should search the file name from
        prebuilts folder. If we can get the correct path from 'prebuilts', we
        can replace it with the incorrect path.

        Args:
            jar_name: The prebuilt jar file name.

        Return:
            A relative prebuilt jar file path if found, otherwise None.
        """
        rel_path = ''
        search = os.sep.join(
            [common_util.get_android_root_dir(), 'prebuilts/**', jar_name])
        results = glob.glob(search, recursive=True)
        if results:
            jar_abs = results[0]
            rel_path = os.path.relpath(
                jar_abs, common_util.get_android_root_dir())
        return rel_path

    def _collect_specific_jars(self):
        """Collect specific types of jar files."""
        if self._is_android_supported_module():
            self._append_jar_from_installed()
        elif self._check_jarjar_rules_exist():
            self._append_jar_from_installed(self.specific_soong_path)
        elif self._check_jars_exist():
            self._set_jars_jarfile()

    def _collect_classes_jars(self):
        """Collect classes jar files."""
        # If there is no source/tests folder of the module, reference the
        # module by jar.
        if not self.src_dirs and not self.test_dirs:
            # Add the classes.jar from the classes_jar attribute as
            # dependency if it exists. If the classes.jar doesn't exist,
            # find the jar file from the installed attribute and add the jar
            # as dependency.
            if self._check_classes_jar_exist():
                self._append_classes_jar()
            else:
                self._append_jar_from_installed()

    def _collect_srcs_and_r_srcs_paths(self):
        """Collect source and R source folder paths for the module."""
        self._collect_specific_jars()
        self._collect_srcs_paths()
        self._collect_classes_jars()
        self._collect_r_srcs_paths()

    def _collect_missing_jars(self):
        """Collect missing jar files to rebuild them."""
        if self.referenced_by_jar and self.missing_jars:
            self.build_targets |= self.missing_jars

    def locate_sources_path(self):
        """Locate source folders' paths or jar files."""
        # Check if users need to reference source according to source depth.
        if not self.module_depth <= self.depth_by_source:
            self._append_jar_from_installed(self.specific_soong_path)
        else:
            self._collect_srcs_and_r_srcs_paths()
        self._collect_missing_jars()


class EclipseModuleData(ModuleData):
    """Deal with modules data for Eclipse

    Only project target modules use source folder type and the other ones use
    jar as their source. We'll combine both to establish the whole project's
    dependencies. If the source folder used to build dependency jar file exists
    in Android, we should provide the jar file path as <linkedResource> item in
    source data.
    """

    def __init__(self, module_name, module_data, project_relpath):
        """Initialize EclipseModuleData.

        Only project target modules apply source folder type, so set the depth
        of module referenced by source to 0.

        Args:
            module_name: String type, name of the module.
            module_data: A dictionary contains a module information.
            project_relpath: A string stands for the project's relative path.
        """
        super().__init__(module_name, module_data, depth=0)
        self.is_project = common_util.is_project_path_relative_module(
            module_data, project_relpath)

    def locate_sources_path(self):
        """Locate source folders' paths or jar files.

        Only collect source folders for the project modules and collect jar
        files for the other dependent modules.
        """
        if self.is_project:
            self._locate_project_source_path()
        else:
            self._locate_jar_path()
        if self.referenced_by_jar and self.missing_jars:
            self.build_targets |= self.missing_jars

    def _locate_project_source_path(self):
        """Locate the source folder paths of the project module.

        A project module is the target modules or paths that users key in
        aidegen command. Collecting the source folders is necessary for
        developers to edit code. And also collect the central R folder for the
        dependency of resources.
        """
        self._collect_srcs_paths()
        self._collect_r_srcs_paths()

    def _locate_jar_path(self):
        """Locate the jar path of the module.

        Use jar files for dependency modules for Eclipse. Collect the jar file
        path with different cases.
        """
        if self._check_jarjar_rules_exist():
            self._append_jar_from_installed(self.specific_soong_path)
        elif self._check_jars_exist():
            self._set_jars_jarfile()
        elif self._check_classes_jar_exist():
            self._append_classes_jar()
        else:
            self._append_jar_from_installed()
