'''
# DataCatalogDatabase

AWS Glue Catalog database for an Amazon S3 dataset.

## Overview

`DataCatalogDatabase` is an [AWS Glue Data Catalog Database](https://docs.aws.amazon.com/glue/latest/dg/define-database.html) configured for an Amazon S3 based dataset:

* The database default location is pointing to an S3 bucket location `s3://<locationBucket>/<locationPrefix>/`
* The database can store various tables structured in their respective prefixes, for example: `s3://<locationBucket>/<locationPrefix>/<table_prefix>/`
* By default, a database level crawler is scheduled to run once a day (00:01h local timezone). The crawler can be disabled and the schedule/frequency of the crawler can be modified with a cron expression.

![Data Catalog Database](../../../website/static/img/adsf-data-catalog.png)

:::caution Data Catalog encryption
The AWS Glue Data Catalog resources created by the `DataCatalogDatabase` construct are not encrypted because the encryption is only available at the catalog level. Changing the encryption at the catalog level has a wide impact on existing Glue resources and producers/consumers. Similarly, changing the encryption configuration at the catalog level after this construct is deployed can break all the resources created as part of DSF on AWS.
:::caution

## Usage

```python
class ExampleDefaultDataCatalogDatabaseStack(cdk.Stack):
    def __init__(self, scope, id):
        super().__init__(scope, id)
        bucket = Bucket(self, "DataCatalogBucket")

        dsf.governance.DataCatalogDatabase(self, "DataCatalogDatabase",
            location_bucket=bucket,
            location_prefix="/databasePath",
            name="example-db"
        )
```

## Modifying the crawler behavior

You can change the default configuration of the AWS Glue Crawler to match your requirements:

* Enable or disable the crawler
* Change the crawler run frequency
* Provide your own key to encrypt the crawler logs

```python
encryption_key = Key(self, "CrawlerLogEncryptionKey")

dsf.governance.DataCatalogDatabase(self, "DataCatalogDatabase",
    location_bucket=bucket,
    location_prefix="/databasePath",
    name="example-db",
    auto_crawl=True,
    auto_crawl_schedule=cdk.aws_glue.CfnCrawler.ScheduleProperty(
        schedule_expression="cron(1 0 * * ? *)"
    ),
    crawler_log_encryption_key=encryption_key,
    crawler_table_level_depth=3
)
```

# DataLakeCatalog

AWS Glue Catalog databases on top of a DataLakeStorage.

## Overview

`DataLakeCatalog` is a data catalog for your data lake. It's a set of [AWS Glue Data Catalog Databases](https://docs.aws.amazon.com/glue/latest/dg/define-database.html) configured on top of a [`DataLakeStorage`](../storage/README.md#datalakestorage).
The construct creates three databases pointing to the respective medallion layers (bronze, silve or gold) of the `DataLakeStorage`:

* The database default location is pointing to the corresponding S3 bucket location `s3://<locationBucket>/<locationPrefix>/`
* By default, each database has an active crawler scheduled to run once a day (00:01h local timezone). The crawler can be disabled and the schedule/frequency of the crawler can be modified with a cron expression.

![Data Lake Catalog](../../../website/static/img/adsf-data-lake-catalog.png)

:::caution Data Catalog encryption
The AWS Glue Data Catalog resources created by the `DataCatalogDatabase` construct are not encrypted because the encryption is only available at the catalog level. Changing the encryption at the catalog level has a wide impact on existing Glue resources and producers/consumers. Similarly, changing the encryption configuration at the catalog level after this construct is deployed can break all the resources created as part of DSF on AWS.
:::caution

## Usage

```python
class ExampleDefaultDataLakeCatalogStack(cdk.Stack):
    def __init__(self, scope, id):
        super().__init__(scope, id)
        storage = dsf.storage.DataLakeStorage(self, "MyDataLakeStorage")

        dsf.governance.DataLakeCatalog(self, "DataCatalog",
            data_lake_storage=storage
        )
```

## Modifying the crawlers behavior for the entire catalog

You can change the default configuration of the AWS Glue Crawlers associated with the different databases to match your requirements:

* Enable or disable the crawlers
* Change the crawlers run frequency
* Provide your own key to encrypt the crawlers logs

The parameters apply to the three databases, if you need fine-grained configuration per database, you can use the [DataCatalogDatabase](#datacatalogdatabase) construct.

```python
encryption_key = Key(self, "CrawlerLogEncryptionKey")

dsf.governance.DataLakeCatalog(self, "DataCatalog",
    data_lake_storage=storage,
    auto_crawl=True,
    auto_crawl_schedule=cdk.aws_glue.CfnCrawler.ScheduleProperty(
        schedule_expression="cron(1 0 * * ? *)"
    ),
    crawler_log_encryption_key=encryption_key,
    crawler_table_level_depth=3
)
```
'''
import abc
import builtins
import datetime
import enum
import typing

import jsii
import publication
import typing_extensions

from typeguard import check_type

from .._jsii import *

import aws_cdk as _aws_cdk_ceddda9d
import aws_cdk.aws_glue as _aws_cdk_aws_glue_ceddda9d
import aws_cdk.aws_iam as _aws_cdk_aws_iam_ceddda9d
import aws_cdk.aws_kms as _aws_cdk_aws_kms_ceddda9d
import aws_cdk.aws_s3 as _aws_cdk_aws_s3_ceddda9d
import constructs as _constructs_77d1e7e8
from ..storage import DataLakeStorage as _DataLakeStorage_3de89668


class DataCatalogDatabase(
    _constructs_77d1e7e8.Construct,
    metaclass=jsii.JSIIMeta,
    jsii_type="aws-dsf.governance.DataCatalogDatabase",
):
    '''An AWS Glue Data Catalog Database configured with the location and a crawler.

    :see: https://awslabs.github.io/data-solutions-framework-on-aws/docs/constructs/library/data-catalog-database

    Example::

        from aws_cdk.aws_s3 import Bucket
        
        
        dsf.governance.DataCatalogDatabase(self, "ExampleDatabase",
            location_bucket=Bucket(scope, "LocationBucket"),
            location_prefix="/databasePath",
            name="example-db"
        )
    '''

    def __init__(
        self,
        scope: _constructs_77d1e7e8.Construct,
        id: builtins.str,
        *,
        location_bucket: _aws_cdk_aws_s3_ceddda9d.IBucket,
        location_prefix: builtins.str,
        name: builtins.str,
        auto_crawl: typing.Optional[builtins.bool] = None,
        auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
        crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
        crawler_role: typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole] = None,
        crawler_table_level_depth: typing.Optional[jsii.Number] = None,
        removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
    ) -> None:
        '''
        :param scope: -
        :param id: -
        :param location_bucket: S3 bucket where data is stored.
        :param location_prefix: Top level location wwhere table data is stored.
        :param name: Database name. Construct would add a randomize suffix as part of the name to prevent name collisions.
        :param auto_crawl: When enabled, this automatically creates a top level Glue Crawler that would run based on the defined schedule in the ``autoCrawlSchedule`` parameter. Default: True
        :param auto_crawl_schedule: The schedule when the Crawler would run. Default is once a day at 00:01h. Default: ``cron(1 0 * * ? *)``
        :param crawler_log_encryption_key: Encryption key used for Crawler logs. Default: Create a new key if none is provided
        :param crawler_role: When passed, the crawler that would be created when ``autoCrawl`` is set to ``True`` would used this role. Additional permissions would be granted to this role such as S3 Bucket read only permissions and KMS encrypt/decrypt on the key used by the Glue Crawler logging to CloudWatch Logs. Default: A new role would be created with least privilege permissions to run the crawler
        :param crawler_table_level_depth: Directory depth where the table folders are located. This helps the crawler understand the layout of the folders in S3. Default: calculated based on ``locationPrefix``
        :param removal_policy: Policy to apply when the bucket is removed from this stack. - @default - RETAIN (The bucket will be orphaned).
        '''
        if __debug__:
            type_hints = typing.get_type_hints(_typecheckingstub__02b60163dd81bf01344f4756bdaf01d47d59bb5d27e793f353b800e34bd3dc61)
            check_type(argname="argument scope", value=scope, expected_type=type_hints["scope"])
            check_type(argname="argument id", value=id, expected_type=type_hints["id"])
        props = DataCatalogDatabaseProps(
            location_bucket=location_bucket,
            location_prefix=location_prefix,
            name=name,
            auto_crawl=auto_crawl,
            auto_crawl_schedule=auto_crawl_schedule,
            crawler_log_encryption_key=crawler_log_encryption_key,
            crawler_role=crawler_role,
            crawler_table_level_depth=crawler_table_level_depth,
            removal_policy=removal_policy,
        )

        jsii.create(self.__class__, self, [scope, id, props])

    @jsii.member(jsii_name="grantReadOnlyAccess")
    def grant_read_only_access(
        self,
        principal: _aws_cdk_aws_iam_ceddda9d.IPrincipal,
    ) -> _aws_cdk_aws_iam_ceddda9d.AddToPrincipalPolicyResult:
        '''Grants read access via identity based policy to the principal.

        This would attach an IAM policy to the principal allowing read access to the database and all its tables.

        :param principal: Principal to attach the database read access to.

        :return: ``AddToPrincipalPolicyResult``
        '''
        if __debug__:
            type_hints = typing.get_type_hints(_typecheckingstub__c52a7b98f577e2ad31e57adcd6cf9de1f5c61ad43fb91e8dce44a74312db25e8)
            check_type(argname="argument principal", value=principal, expected_type=type_hints["principal"])
        return typing.cast(_aws_cdk_aws_iam_ceddda9d.AddToPrincipalPolicyResult, jsii.invoke(self, "grantReadOnlyAccess", [principal]))

    @jsii.member(jsii_name="retrieveVersion")
    def retrieve_version(self) -> typing.Any:
        '''Retrieve DSF package.json version.'''
        return typing.cast(typing.Any, jsii.invoke(self, "retrieveVersion", []))

    @jsii.python.classproperty
    @jsii.member(jsii_name="DSF_OWNED_TAG")
    def DSF_OWNED_TAG(cls) -> builtins.str:
        return typing.cast(builtins.str, jsii.sget(cls, "DSF_OWNED_TAG"))

    @jsii.python.classproperty
    @jsii.member(jsii_name="DSF_TRACKING_CODE")
    def DSF_TRACKING_CODE(cls) -> builtins.str:
        return typing.cast(builtins.str, jsii.sget(cls, "DSF_TRACKING_CODE"))

    @builtins.property
    @jsii.member(jsii_name="database")
    def database(self) -> _aws_cdk_aws_glue_ceddda9d.CfnDatabase:
        '''The Glue database that's created.'''
        return typing.cast(_aws_cdk_aws_glue_ceddda9d.CfnDatabase, jsii.get(self, "database"))

    @builtins.property
    @jsii.member(jsii_name="databaseName")
    def database_name(self) -> builtins.str:
        '''The Glue database name with the randomized suffix to prevent name collisions in the catalog.'''
        return typing.cast(builtins.str, jsii.get(self, "databaseName"))

    @builtins.property
    @jsii.member(jsii_name="crawler")
    def crawler(self) -> typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnCrawler]:
        '''The Glue Crawler that is automatically created when ``autoCrawl`` is set to ``true`` (default value).

        This property can be undefined if ``autoCrawl`` is set to ``false``.
        '''
        return typing.cast(typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnCrawler], jsii.get(self, "crawler"))

    @builtins.property
    @jsii.member(jsii_name="crawlerLogEncryptionKey")
    def crawler_log_encryption_key(
        self,
    ) -> typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey]:
        '''KMS encryption key used by the Crawler.'''
        return typing.cast(typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey], jsii.get(self, "crawlerLogEncryptionKey"))

    @builtins.property
    @jsii.member(jsii_name="crawlerRole")
    def crawler_role(self) -> typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole]:
        '''The IAM role used by the Glue crawler when created.'''
        return typing.cast(typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole], jsii.get(self, "crawlerRole"))

    @builtins.property
    @jsii.member(jsii_name="crawlerSecurityConfiguration")
    def crawler_security_configuration(
        self,
    ) -> typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnSecurityConfiguration]:
        '''The Glue security configuration used by the Glue Crawler when created.'''
        return typing.cast(typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnSecurityConfiguration], jsii.get(self, "crawlerSecurityConfiguration"))


@jsii.data_type(
    jsii_type="aws-dsf.governance.DataCatalogDatabaseProps",
    jsii_struct_bases=[],
    name_mapping={
        "location_bucket": "locationBucket",
        "location_prefix": "locationPrefix",
        "name": "name",
        "auto_crawl": "autoCrawl",
        "auto_crawl_schedule": "autoCrawlSchedule",
        "crawler_log_encryption_key": "crawlerLogEncryptionKey",
        "crawler_role": "crawlerRole",
        "crawler_table_level_depth": "crawlerTableLevelDepth",
        "removal_policy": "removalPolicy",
    },
)
class DataCatalogDatabaseProps:
    def __init__(
        self,
        *,
        location_bucket: _aws_cdk_aws_s3_ceddda9d.IBucket,
        location_prefix: builtins.str,
        name: builtins.str,
        auto_crawl: typing.Optional[builtins.bool] = None,
        auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
        crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
        crawler_role: typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole] = None,
        crawler_table_level_depth: typing.Optional[jsii.Number] = None,
        removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
    ) -> None:
        '''The Database catalog properties.

        :param location_bucket: S3 bucket where data is stored.
        :param location_prefix: Top level location wwhere table data is stored.
        :param name: Database name. Construct would add a randomize suffix as part of the name to prevent name collisions.
        :param auto_crawl: When enabled, this automatically creates a top level Glue Crawler that would run based on the defined schedule in the ``autoCrawlSchedule`` parameter. Default: True
        :param auto_crawl_schedule: The schedule when the Crawler would run. Default is once a day at 00:01h. Default: ``cron(1 0 * * ? *)``
        :param crawler_log_encryption_key: Encryption key used for Crawler logs. Default: Create a new key if none is provided
        :param crawler_role: When passed, the crawler that would be created when ``autoCrawl`` is set to ``True`` would used this role. Additional permissions would be granted to this role such as S3 Bucket read only permissions and KMS encrypt/decrypt on the key used by the Glue Crawler logging to CloudWatch Logs. Default: A new role would be created with least privilege permissions to run the crawler
        :param crawler_table_level_depth: Directory depth where the table folders are located. This helps the crawler understand the layout of the folders in S3. Default: calculated based on ``locationPrefix``
        :param removal_policy: Policy to apply when the bucket is removed from this stack. - @default - RETAIN (The bucket will be orphaned).
        '''
        if isinstance(auto_crawl_schedule, dict):
            auto_crawl_schedule = _aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty(**auto_crawl_schedule)
        if __debug__:
            type_hints = typing.get_type_hints(_typecheckingstub__37a758c0e652ca1023a333c00758b1834f5202b87981b74f4ca9ddc7bc435fe7)
            check_type(argname="argument location_bucket", value=location_bucket, expected_type=type_hints["location_bucket"])
            check_type(argname="argument location_prefix", value=location_prefix, expected_type=type_hints["location_prefix"])
            check_type(argname="argument name", value=name, expected_type=type_hints["name"])
            check_type(argname="argument auto_crawl", value=auto_crawl, expected_type=type_hints["auto_crawl"])
            check_type(argname="argument auto_crawl_schedule", value=auto_crawl_schedule, expected_type=type_hints["auto_crawl_schedule"])
            check_type(argname="argument crawler_log_encryption_key", value=crawler_log_encryption_key, expected_type=type_hints["crawler_log_encryption_key"])
            check_type(argname="argument crawler_role", value=crawler_role, expected_type=type_hints["crawler_role"])
            check_type(argname="argument crawler_table_level_depth", value=crawler_table_level_depth, expected_type=type_hints["crawler_table_level_depth"])
            check_type(argname="argument removal_policy", value=removal_policy, expected_type=type_hints["removal_policy"])
        self._values: typing.Dict[builtins.str, typing.Any] = {
            "location_bucket": location_bucket,
            "location_prefix": location_prefix,
            "name": name,
        }
        if auto_crawl is not None:
            self._values["auto_crawl"] = auto_crawl
        if auto_crawl_schedule is not None:
            self._values["auto_crawl_schedule"] = auto_crawl_schedule
        if crawler_log_encryption_key is not None:
            self._values["crawler_log_encryption_key"] = crawler_log_encryption_key
        if crawler_role is not None:
            self._values["crawler_role"] = crawler_role
        if crawler_table_level_depth is not None:
            self._values["crawler_table_level_depth"] = crawler_table_level_depth
        if removal_policy is not None:
            self._values["removal_policy"] = removal_policy

    @builtins.property
    def location_bucket(self) -> _aws_cdk_aws_s3_ceddda9d.IBucket:
        '''S3 bucket where data is stored.'''
        result = self._values.get("location_bucket")
        assert result is not None, "Required property 'location_bucket' is missing"
        return typing.cast(_aws_cdk_aws_s3_ceddda9d.IBucket, result)

    @builtins.property
    def location_prefix(self) -> builtins.str:
        '''Top level location wwhere table data is stored.'''
        result = self._values.get("location_prefix")
        assert result is not None, "Required property 'location_prefix' is missing"
        return typing.cast(builtins.str, result)

    @builtins.property
    def name(self) -> builtins.str:
        '''Database name.

        Construct would add a randomize suffix as part of the name to prevent name collisions.
        '''
        result = self._values.get("name")
        assert result is not None, "Required property 'name' is missing"
        return typing.cast(builtins.str, result)

    @builtins.property
    def auto_crawl(self) -> typing.Optional[builtins.bool]:
        '''When enabled, this automatically creates a top level Glue Crawler that would run based on the defined schedule in the ``autoCrawlSchedule`` parameter.

        :default: True
        '''
        result = self._values.get("auto_crawl")
        return typing.cast(typing.Optional[builtins.bool], result)

    @builtins.property
    def auto_crawl_schedule(
        self,
    ) -> typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty]:
        '''The schedule when the Crawler would run.

        Default is once a day at 00:01h.

        :default: ``cron(1 0 * * ? *)``
        '''
        result = self._values.get("auto_crawl_schedule")
        return typing.cast(typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty], result)

    @builtins.property
    def crawler_log_encryption_key(
        self,
    ) -> typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey]:
        '''Encryption key used for Crawler logs.

        :default: Create a new key if none is provided
        '''
        result = self._values.get("crawler_log_encryption_key")
        return typing.cast(typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey], result)

    @builtins.property
    def crawler_role(self) -> typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole]:
        '''When passed, the crawler that would be created when ``autoCrawl`` is set to ``True`` would used this role.

        Additional permissions would be granted to this role such as S3 Bucket read only permissions and KMS encrypt/decrypt on the key used by the Glue Crawler logging to CloudWatch Logs.

        :default: A new role would be created with least privilege permissions to run the crawler
        '''
        result = self._values.get("crawler_role")
        return typing.cast(typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole], result)

    @builtins.property
    def crawler_table_level_depth(self) -> typing.Optional[jsii.Number]:
        '''Directory depth where the table folders are located.

        This helps the crawler understand the layout of the folders in S3.

        :default: calculated based on ``locationPrefix``
        '''
        result = self._values.get("crawler_table_level_depth")
        return typing.cast(typing.Optional[jsii.Number], result)

    @builtins.property
    def removal_policy(self) -> typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy]:
        '''Policy to apply when the bucket is removed from this stack.

        - @default - RETAIN (The bucket will be orphaned).
        '''
        result = self._values.get("removal_policy")
        return typing.cast(typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy], result)

    def __eq__(self, rhs: typing.Any) -> builtins.bool:
        return isinstance(rhs, self.__class__) and rhs._values == self._values

    def __ne__(self, rhs: typing.Any) -> builtins.bool:
        return not (rhs == self)

    def __repr__(self) -> str:
        return "DataCatalogDatabaseProps(%s)" % ", ".join(
            k + "=" + repr(v) for k, v in self._values.items()
        )


class DataLakeCatalog(
    _constructs_77d1e7e8.Construct,
    metaclass=jsii.JSIIMeta,
    jsii_type="aws-dsf.governance.DataLakeCatalog",
):
    '''Creates AWS Glue Catalog Database for each storage layer.

    Composed of 3 {@link DataCatalogDatabase} for Bronze, Silver, and Gold data.

    :see: https://awslabs.github.io/data-solutions-framework-on-aws/docs/constructs/library/data-lake-catalog

    Example::

        from aws_cdk.aws_kms import Key
        
        
        log_encryption_key = Key(self, "LogEncryptionKey")
        storage = dsf.storage.DataLakeStorage(self, "ExampleStorage")
        data_lake_catalog = dsf.governance.DataLakeCatalog(self, "ExampleDataLakeCatalog",
            data_lake_storage=storage,
            database_name="exampledb",
            crawler_log_encryption_key=log_encryption_key
        )
    '''

    def __init__(
        self,
        scope: _constructs_77d1e7e8.Construct,
        id: builtins.str,
        *,
        data_lake_storage: _DataLakeStorage_3de89668,
        auto_crawl: typing.Optional[builtins.bool] = None,
        auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
        crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
        crawler_table_level_depth: typing.Optional[jsii.Number] = None,
        database_name: typing.Optional[builtins.str] = None,
        removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
    ) -> None:
        '''Constructs a new instance of DataLakeCatalog.

        :param scope: the Scope of the CDK Construct.
        :param id: the ID of the CDK Construct.
        :param data_lake_storage: Location of data lake files.
        :param auto_crawl: When enabled, this automatically creates a top level Glue Crawler that would run based on the defined schedule in the ``autoCrawlSchedule`` parameter. Default: True
        :param auto_crawl_schedule: The schedule when the Crawler would run. Default is once a day at 00:01h. Default: ``cron(1 0 * * ? *)``
        :param crawler_log_encryption_key: Encryption key used for Crawler logs. Default: Create a new key if none is provided
        :param crawler_table_level_depth: Directory depth where the table folders are located. This helps the crawler understand the layout of the folders in S3. Default: calculated based on ``locationPrefix``
        :param database_name: The suffix of the database in the Glue Data Catalog. The name of the database is composed of the bucket name and this suffix. The suffix is also added to the S3 location inside the data lake buckets. Default: Use the bucket name as the database name and / as the S3 location
        :param removal_policy: Policy to apply when the bucket is removed from this stack. - @default - RETAIN (The bucket will be orphaned).
        '''
        if __debug__:
            type_hints = typing.get_type_hints(_typecheckingstub__6b5067efe3a97663930678cb7c0a1bf2ba1533cf290f81cabbb69e0d4625f705)
            check_type(argname="argument scope", value=scope, expected_type=type_hints["scope"])
            check_type(argname="argument id", value=id, expected_type=type_hints["id"])
        props = DataLakeCatalogProps(
            data_lake_storage=data_lake_storage,
            auto_crawl=auto_crawl,
            auto_crawl_schedule=auto_crawl_schedule,
            crawler_log_encryption_key=crawler_log_encryption_key,
            crawler_table_level_depth=crawler_table_level_depth,
            database_name=database_name,
            removal_policy=removal_policy,
        )

        jsii.create(self.__class__, self, [scope, id, props])

    @jsii.member(jsii_name="retrieveVersion")
    def retrieve_version(self) -> typing.Any:
        '''Retrieve DSF package.json version.'''
        return typing.cast(typing.Any, jsii.invoke(self, "retrieveVersion", []))

    @jsii.python.classproperty
    @jsii.member(jsii_name="DSF_OWNED_TAG")
    def DSF_OWNED_TAG(cls) -> builtins.str:
        return typing.cast(builtins.str, jsii.sget(cls, "DSF_OWNED_TAG"))

    @jsii.python.classproperty
    @jsii.member(jsii_name="DSF_TRACKING_CODE")
    def DSF_TRACKING_CODE(cls) -> builtins.str:
        return typing.cast(builtins.str, jsii.sget(cls, "DSF_TRACKING_CODE"))

    @builtins.property
    @jsii.member(jsii_name="bronzeCatalogDatabase")
    def bronze_catalog_database(self) -> DataCatalogDatabase:
        '''The Glue Database for Bronze bucket.'''
        return typing.cast(DataCatalogDatabase, jsii.get(self, "bronzeCatalogDatabase"))

    @builtins.property
    @jsii.member(jsii_name="goldCatalogDatabase")
    def gold_catalog_database(self) -> DataCatalogDatabase:
        '''The Glue Database for Gold bucket.'''
        return typing.cast(DataCatalogDatabase, jsii.get(self, "goldCatalogDatabase"))

    @builtins.property
    @jsii.member(jsii_name="silverCatalogDatabase")
    def silver_catalog_database(self) -> DataCatalogDatabase:
        '''The Glue Database for Silver bucket.'''
        return typing.cast(DataCatalogDatabase, jsii.get(self, "silverCatalogDatabase"))

    @builtins.property
    @jsii.member(jsii_name="crawlerLogEncryptionKey")
    def crawler_log_encryption_key(
        self,
    ) -> typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey]:
        '''The KMS Key used to encrypt the crawler logs.'''
        return typing.cast(typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey], jsii.get(self, "crawlerLogEncryptionKey"))


@jsii.data_type(
    jsii_type="aws-dsf.governance.DataLakeCatalogProps",
    jsii_struct_bases=[],
    name_mapping={
        "data_lake_storage": "dataLakeStorage",
        "auto_crawl": "autoCrawl",
        "auto_crawl_schedule": "autoCrawlSchedule",
        "crawler_log_encryption_key": "crawlerLogEncryptionKey",
        "crawler_table_level_depth": "crawlerTableLevelDepth",
        "database_name": "databaseName",
        "removal_policy": "removalPolicy",
    },
)
class DataLakeCatalogProps:
    def __init__(
        self,
        *,
        data_lake_storage: _DataLakeStorage_3de89668,
        auto_crawl: typing.Optional[builtins.bool] = None,
        auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
        crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
        crawler_table_level_depth: typing.Optional[jsii.Number] = None,
        database_name: typing.Optional[builtins.str] = None,
        removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
    ) -> None:
        '''Properties for the DataLakeCatalog Construct.

        :param data_lake_storage: Location of data lake files.
        :param auto_crawl: When enabled, this automatically creates a top level Glue Crawler that would run based on the defined schedule in the ``autoCrawlSchedule`` parameter. Default: True
        :param auto_crawl_schedule: The schedule when the Crawler would run. Default is once a day at 00:01h. Default: ``cron(1 0 * * ? *)``
        :param crawler_log_encryption_key: Encryption key used for Crawler logs. Default: Create a new key if none is provided
        :param crawler_table_level_depth: Directory depth where the table folders are located. This helps the crawler understand the layout of the folders in S3. Default: calculated based on ``locationPrefix``
        :param database_name: The suffix of the database in the Glue Data Catalog. The name of the database is composed of the bucket name and this suffix. The suffix is also added to the S3 location inside the data lake buckets. Default: Use the bucket name as the database name and / as the S3 location
        :param removal_policy: Policy to apply when the bucket is removed from this stack. - @default - RETAIN (The bucket will be orphaned).
        '''
        if isinstance(auto_crawl_schedule, dict):
            auto_crawl_schedule = _aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty(**auto_crawl_schedule)
        if __debug__:
            type_hints = typing.get_type_hints(_typecheckingstub__5fe8cedbd5eb11d346139bf10aa6f72c49c02c5fb669897a6474e3b974764233)
            check_type(argname="argument data_lake_storage", value=data_lake_storage, expected_type=type_hints["data_lake_storage"])
            check_type(argname="argument auto_crawl", value=auto_crawl, expected_type=type_hints["auto_crawl"])
            check_type(argname="argument auto_crawl_schedule", value=auto_crawl_schedule, expected_type=type_hints["auto_crawl_schedule"])
            check_type(argname="argument crawler_log_encryption_key", value=crawler_log_encryption_key, expected_type=type_hints["crawler_log_encryption_key"])
            check_type(argname="argument crawler_table_level_depth", value=crawler_table_level_depth, expected_type=type_hints["crawler_table_level_depth"])
            check_type(argname="argument database_name", value=database_name, expected_type=type_hints["database_name"])
            check_type(argname="argument removal_policy", value=removal_policy, expected_type=type_hints["removal_policy"])
        self._values: typing.Dict[builtins.str, typing.Any] = {
            "data_lake_storage": data_lake_storage,
        }
        if auto_crawl is not None:
            self._values["auto_crawl"] = auto_crawl
        if auto_crawl_schedule is not None:
            self._values["auto_crawl_schedule"] = auto_crawl_schedule
        if crawler_log_encryption_key is not None:
            self._values["crawler_log_encryption_key"] = crawler_log_encryption_key
        if crawler_table_level_depth is not None:
            self._values["crawler_table_level_depth"] = crawler_table_level_depth
        if database_name is not None:
            self._values["database_name"] = database_name
        if removal_policy is not None:
            self._values["removal_policy"] = removal_policy

    @builtins.property
    def data_lake_storage(self) -> _DataLakeStorage_3de89668:
        '''Location of data lake files.'''
        result = self._values.get("data_lake_storage")
        assert result is not None, "Required property 'data_lake_storage' is missing"
        return typing.cast(_DataLakeStorage_3de89668, result)

    @builtins.property
    def auto_crawl(self) -> typing.Optional[builtins.bool]:
        '''When enabled, this automatically creates a top level Glue Crawler that would run based on the defined schedule in the ``autoCrawlSchedule`` parameter.

        :default: True
        '''
        result = self._values.get("auto_crawl")
        return typing.cast(typing.Optional[builtins.bool], result)

    @builtins.property
    def auto_crawl_schedule(
        self,
    ) -> typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty]:
        '''The schedule when the Crawler would run.

        Default is once a day at 00:01h.

        :default: ``cron(1 0 * * ? *)``
        '''
        result = self._values.get("auto_crawl_schedule")
        return typing.cast(typing.Optional[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty], result)

    @builtins.property
    def crawler_log_encryption_key(
        self,
    ) -> typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey]:
        '''Encryption key used for Crawler logs.

        :default: Create a new key if none is provided
        '''
        result = self._values.get("crawler_log_encryption_key")
        return typing.cast(typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey], result)

    @builtins.property
    def crawler_table_level_depth(self) -> typing.Optional[jsii.Number]:
        '''Directory depth where the table folders are located.

        This helps the crawler understand the layout of the folders in S3.

        :default: calculated based on ``locationPrefix``
        '''
        result = self._values.get("crawler_table_level_depth")
        return typing.cast(typing.Optional[jsii.Number], result)

    @builtins.property
    def database_name(self) -> typing.Optional[builtins.str]:
        '''The suffix of the database in the Glue Data Catalog.

        The name of the database is composed of the bucket name and this suffix.
        The suffix is also added to the S3 location inside the data lake buckets.

        :default: Use the bucket name as the database name and / as the S3 location
        '''
        result = self._values.get("database_name")
        return typing.cast(typing.Optional[builtins.str], result)

    @builtins.property
    def removal_policy(self) -> typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy]:
        '''Policy to apply when the bucket is removed from this stack.

        - @default - RETAIN (The bucket will be orphaned).
        '''
        result = self._values.get("removal_policy")
        return typing.cast(typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy], result)

    def __eq__(self, rhs: typing.Any) -> builtins.bool:
        return isinstance(rhs, self.__class__) and rhs._values == self._values

    def __ne__(self, rhs: typing.Any) -> builtins.bool:
        return not (rhs == self)

    def __repr__(self) -> str:
        return "DataLakeCatalogProps(%s)" % ", ".join(
            k + "=" + repr(v) for k, v in self._values.items()
        )


__all__ = [
    "DataCatalogDatabase",
    "DataCatalogDatabaseProps",
    "DataLakeCatalog",
    "DataLakeCatalogProps",
]

publication.publish()

def _typecheckingstub__02b60163dd81bf01344f4756bdaf01d47d59bb5d27e793f353b800e34bd3dc61(
    scope: _constructs_77d1e7e8.Construct,
    id: builtins.str,
    *,
    location_bucket: _aws_cdk_aws_s3_ceddda9d.IBucket,
    location_prefix: builtins.str,
    name: builtins.str,
    auto_crawl: typing.Optional[builtins.bool] = None,
    auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
    crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
    crawler_role: typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole] = None,
    crawler_table_level_depth: typing.Optional[jsii.Number] = None,
    removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
) -> None:
    """Type checking stubs"""
    pass

def _typecheckingstub__c52a7b98f577e2ad31e57adcd6cf9de1f5c61ad43fb91e8dce44a74312db25e8(
    principal: _aws_cdk_aws_iam_ceddda9d.IPrincipal,
) -> None:
    """Type checking stubs"""
    pass

def _typecheckingstub__37a758c0e652ca1023a333c00758b1834f5202b87981b74f4ca9ddc7bc435fe7(
    *,
    location_bucket: _aws_cdk_aws_s3_ceddda9d.IBucket,
    location_prefix: builtins.str,
    name: builtins.str,
    auto_crawl: typing.Optional[builtins.bool] = None,
    auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
    crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
    crawler_role: typing.Optional[_aws_cdk_aws_iam_ceddda9d.IRole] = None,
    crawler_table_level_depth: typing.Optional[jsii.Number] = None,
    removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
) -> None:
    """Type checking stubs"""
    pass

def _typecheckingstub__6b5067efe3a97663930678cb7c0a1bf2ba1533cf290f81cabbb69e0d4625f705(
    scope: _constructs_77d1e7e8.Construct,
    id: builtins.str,
    *,
    data_lake_storage: _DataLakeStorage_3de89668,
    auto_crawl: typing.Optional[builtins.bool] = None,
    auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
    crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
    crawler_table_level_depth: typing.Optional[jsii.Number] = None,
    database_name: typing.Optional[builtins.str] = None,
    removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
) -> None:
    """Type checking stubs"""
    pass

def _typecheckingstub__5fe8cedbd5eb11d346139bf10aa6f72c49c02c5fb669897a6474e3b974764233(
    *,
    data_lake_storage: _DataLakeStorage_3de89668,
    auto_crawl: typing.Optional[builtins.bool] = None,
    auto_crawl_schedule: typing.Optional[typing.Union[_aws_cdk_aws_glue_ceddda9d.CfnCrawler.ScheduleProperty, typing.Dict[builtins.str, typing.Any]]] = None,
    crawler_log_encryption_key: typing.Optional[_aws_cdk_aws_kms_ceddda9d.IKey] = None,
    crawler_table_level_depth: typing.Optional[jsii.Number] = None,
    database_name: typing.Optional[builtins.str] = None,
    removal_policy: typing.Optional[_aws_cdk_ceddda9d.RemovalPolicy] = None,
) -> None:
    """Type checking stubs"""
    pass
