text:
from collections import OrderedDict
import os
import re
from typing import Dict, Mapping, Optional, Iterable, Sequence, Tuple, Type, Union
import pkg_resources

from google.api_core import client_options as client_options_lib
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1
from google.api_core import retry as retries
from google.auth import credentials as ga_credentials  # type: ignore
from google.auth.transport import mtls  # type: ignore
from google.auth.transport.grpc import SslCredentials  # type: ignore
from google.auth.exceptions import MutualTLSChannelError  # type: ignore
from google.oauth2 import service_account  # type: ignore

try:
    OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault]
except AttributeError:  # pragma: NO COVER
    OptionalRetry = Union[retries.Retry, object]  # type: ignore

from google.cloud.aiplatform_v1beta1.types import featurestore_online_service
from google.cloud.location import locations_pb2  # type: ignore
from google.iam.v1 import iam_policy_pb2  # type: ignore
from google.iam.v1 import policy_pb2  # type: ignore
from google.longrunning import operations_pb2
from .transports.base import (
    FeaturestoreOnlineServingServiceTransport,
    DEFAULT_CLIENT_INFO,
)
from .transports.grpc import FeaturestoreOnlineServingServiceGrpcTransport
from .transports.grpc_asyncio import (
    FeaturestoreOnlineServingServiceGrpcAsyncIOTransport,
)

class FeaturestoreOnlineServingServiceClientMeta(type):
    """Metaclass for the FeaturestoreOnlineServingService client.

    This provides class-level methods for building and retrieving
    support objects (e.g. transport) without polluting the client instance
    objects.
    """

    _transport_registry = (
        OrderedDict()
    )  # type: Dict[str, Type[FeaturestoreOnlineServingServiceTransport]]
    _transport_registry["grpc"] = FeaturestoreOnlineServingServiceGrpcTransport
    _transport_registry[
        "grpc_asyncio"
    ] = FeaturestoreOnlineServingServiceGrpcAsyncIOTransport

    def get_transport_class(
        cls,
        label: str = None,
    ) -> Type[FeaturestoreOnlineServingServiceTransport]:
        """Returns an appropriate transport class.

        Args:
            label: The name of the desired transport. If none is
                provided, then the first transport in the registry is used.

        Returns:
            The transport class to use.
        """
        # If a specific transport is requested, return that one.
        if label:
            return cls._transport_registry[label]

        # No transport is requested; return the default (that is, the first one
        # in the dictionary).
        return next(iter(cls._transport_registry.values()))

class FeaturestoreOnlineServingServiceClient(
    metaclass=FeaturestoreOnlineServingServiceClientMeta
):
    """A service for serving online feature values."""

    @staticmethod
    def _get_default_mtls_endpoint(api_endpoint):
        """Converts api endpoint to mTLS endpoint.

        Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
        "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
        Args:
            api_endpoint (Optional[str]): the api endpoint to convert.
        Returns:
            str: converted mTLS api endpoint.
        """
        if not api_endpoint:
            return api_endpoint

        mtls_endpoint_re = re.compile(
            r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
        )

        m = mtls_endpoint_re.match(api_endpoint)
        name, mtls, sandbox, googledomain = m.groups()
        if mtls or not googledomain:
            return api_endpoint

        if sandbox:
            return api_endpoint.replace(
                "sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
            )

        return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")

    DEFAULT_ENDPOINT = "aiplatform.googleapis.com"
    DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__(  # type: ignore
        DEFAULT_ENDPOINT
    )

    @classmethod
    def from_service_account_info(cls, info: dict, *args, **kwargs):
        """Creates an instance of this client using the provided credentials
            info.

        Args:
            info (dict): The service account private key info.
            args: Additional arguments to pass to the constructor.
            kwargs: Additional arguments to pass to the constructor.

        Returns:
            FeaturestoreOnlineServingServiceClient: The constructed client.
        """
        credentials = service_account.Credentials.from_service_account_info(info)
        kwargs["credentials"] = credentials
        return cls(*args, **kwargs)

    @classmethod
    def from_service_account_file(cls, filename: str, *args, **kwargs):
        """Creates an instance of this client using the provided credentials
            file.

        Args:
            filename (str): The path to the service account private key json
                file.
            args: Additional arguments to pass to the constructor.
            kwargs: Additional arguments to pass to the constructor.

        Returns:
            FeaturestoreOnlineServingServiceClient: The constructed client.
        """
        credentials = service_account.Credentials.from_service_account_file(filename)
        kwargs["credentials"] = credentials
        return cls(*args, **kwargs)

    from_service_account_json = from_service_account_file

    @property
    def transport(self) -> FeaturestoreOnlineServingServiceTransport:
        """Returns the transport used by the client instance.

        Returns:
            FeaturestoreOnlineServingServiceTransport: The transport used by the client
                instance.
        """
        return self._transport

    @staticmethod
    def entity_type_path(
        project: str,
        location: str,
        featurestore: str,
        entity_type: str,
    ) -> str:
        """Returns a fully-qualified entity_type string."""
        return "projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entity_type}".format(
            project=project,
            location=location,
            featurestore=featurestore,
            entity_type=entity_type,
        )

    @staticmethod
    def parse_entity_type_path(path: str) -> Dict[str, str]:
        """Parses a entity_type path into its component segments."""
        m = re.match(
            r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)/featurestores/(?P<featurestore>.+?)/entityTypes/(?P<entity_type>.+?)$",
            path,
        )
        return m.groupdict() if m else {}

    @staticmethod
    def common_billing_account_path(
        billing_account: str,
    ) -> str:
        """Returns a fully-qualified billing_account string."""
        return "billingAccounts/{billing_account}".format(
            billing_account=billing_account,
        )

    @staticmethod
    def parse_common_billing_account_path(path: str) -> Dict[str, str]:
        """Parse a billing_account path into its component segments."""
        m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path)
        return m.groupdict() if m else {}

    @staticmethod
    def common_folder_path(
        folder: str,
    ) -> str:
        """Returns a fully-qualified folder string."""
        return "folders/{folder}".format(
            folder=folder,
        )

    @staticmethod
    def parse_common_folder_path(path: str) -> Dict[str, str]:
        """Parse a folder path into its component segments."""
        m = re.match(r"^folders/(?P<folder>.+?)$", path)
        return m.groupdict() if m else {}

    @staticmethod
    def common_organization_path(
        organization: str,
    ) -> str:
        """Returns a fully-qualified organization string."""
        return "organizations/{organization}".format(
            organization=organization,
        )

    @staticmethod
    def parse_common_organization_path(path: str) -> Dict[str, str]:
        """Parse a organization path into its component segments."""
        m = re.match(r"^organizations/(?P<organization>.+?)$", path)
        return m.groupdict() if m else {}

    @staticmethod
    def common_project_path(
        project: str,
    ) -> str:
        """Returns a fully-qualified project string."""
        return "projects/{project}".format(
            project=project,
        )

    @staticmethod
    def parse_common_project_path(path: str) -> Dict[str, str]:
        """Parse a project path into its component segments."""
        m = re.match(r"^projects/(?P<project>.+?)$", path)
        return m.groupdict() if m else {}

    @staticmethod
    def common_location_path(
        project: str,
        location: str,
    ) -> str:
        """Returns a fully-qualified location string."""
        return "projects/{project}/locations/{location}".format(
            project=project,
            location=location,
        )

    @staticmethod
    def parse_common_location_path(path: str) -> Dict[str, str]:
        """Parse a location path into its component segments."""
        m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path)
        return m.groupdict() if m else {}

    @classmethod
    def get_mtls_endpoint_and_cert_source(
        cls, client_options: Optional[client_options_lib.ClientOptions] = None
    ):
        """Return the API endpoint and client cert source for mutual TLS.

        The client cert source is determined in the following order:
        (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
        client cert source is None.
        (2) if `client_options.client_cert_source` is provided, use the provided one; if the
        default client cert source exists, use the default one; otherwise the client cert
        source is None.

        The API endpoint is determined in the following order:
        (1) if `client_options.api_endpoint` if provided, use the provided one.
        (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
        default mTLS endpoint; if the environment variabel is "never", use the default API
        endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
        use the default API endpoint.

        More details can be found at https://google.aip.dev/auth/4114.

        Args:
            client_options (google.api_core.client_options.ClientOptions): Custom options for the
                client. Only the `api_endpoint` and `client_cert_source` properties may be used
                in this method.

        Returns:
            Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
                client cert source to use.

        Raises:
            google.auth.exceptions.MutualTLSChannelError: If any errors happen.
        """
        if client_options is None:
            client_options = client_options_lib.ClientOptions()
        use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
        use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
        if use_client_cert not in ("true", "false"):
            raise ValueError(
                "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
            )
        if use_mtls_endpoint not in ("auto", "never", "always"):
            raise MutualTLSChannelError(
                "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
            )

        # Figure out the client cert source to use.
        client_cert_source = None
        if use_client_cert == "true":
            if client_options.client_cert_source:
                client_cert_source = client_options.client_cert_source
            elif mtls.has_default_client_cert_source():
                client_cert_source = mtls.default_client_cert_source()

        # Figure out which api endpoint to use.
        if client_options.api_endpoint is not None:
            api_endpoint = client_options.api_endpoint
        elif use_mtls_endpoint == "always" or (
            use_mtls_endpoint == "auto" and client_cert_source
        ):
            api_endpoint = cls.DEFAULT_MTLS_ENDPOINT
        else:
            api_endpoint = cls.DEFAULT_ENDPOINT

        return api_endpoint, client_cert_source

    def __init__(
        self,
        *,
        credentials: Optional[ga_credentials.Credentials] = None,
        transport: Union[str, FeaturestoreOnlineServingServiceTransport, None] = None,
        client_options: Optional[client_options_lib.ClientOptions] = None,
        client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
    ) -> None:
        """Instantiates the featurestore online serving service client.

        Args:
            credentials (Optional[google.auth.credentials.Credentials]): The
                authorization credentials to attach to requests. These
                credentials identify the application to the service; if none
                are specified, the client will attempt to ascertain the
                credentials from the environment.
            transport (Union[str, FeaturestoreOnlineServingServiceTransport]): The
                transport to use. If set to None, a transport is chosen
                automatically.
            client_options (google.api_core.client_options.ClientOptions): Custom options for the
                client. It won't take effect if a ``transport`` instance is provided.
                (1) The ``api_endpoint`` property can be used to override the
                default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
                environment variable can also be used to override the endpoint:
                "always" (always use the default mTLS endpoint), "never" (always
                use the default regular endpoint) and "auto" (auto switch to the
                default mTLS endpoint if client certificate is present, this is
                the default value). However, the ``api_endpoint`` property takes
                precedence if provided.
                (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
                is "true", then the ``client_cert_source`` property can be used
                to provide client certificate for mutual TLS transport. If
                not provided, the default SSL client certificate will be used if
                present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
                set, no client certificate will be used.
            client_info (google.api_core.gapic_v1.client_info.ClientInfo):
                The client info used to send a user-agent string along with
                API requests. If ``None``, then default info will be used.
                Generally, you only need to set this if you're developing
                your own client library.

        Raises:
            google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
                creation failed for any reason.
        """
        if isinstance(client_options, dict):
            client_options = client_options_lib.from_dict(client_options)
        if client_options is None:
            client_options = client_options_lib.ClientOptions()

        api_endpoint, client_cert_source_func = self.get_mtls_endpoint_and_cert_source(
            client_options
        )

        api_key_value = getattr(client_options, "api_key", None)
        if api_key_value and credentials:
            raise ValueError(
                "client_options.api_key and credentials are mutually exclusive"
            )

        # Save or instantiate the transport.
        # Ordinarily, we provide the transport, but allowing a custom transport
        # instance provides an extensibility point for unusual situations.
        if isinstance(transport, FeaturestoreOnlineServingServiceTransport):
            # transport is a FeaturestoreOnlineServingServiceTransport instance.
            if credentials or client_options.credentials_file or api_key_value:
                raise ValueError(
                    "When providing a transport instance, "
                    "provide its credentials directly."
                )
            if client_options.scopes:
                raise ValueError(
                    "When providing a transport instance, provide its scopes "
                    "directly."
                )
            self._transport = transport
        else:
            import google.auth._default  # type: ignore

            if api_key_value and hasattr(
                google.auth._default, "get_api_key_credentials"
            ):
                credentials = google.auth._default.get_api_key_credentials(
                    api_key_value
                )

            Transport = type(self).get_transport_class(transport)
            self._transport = Transport(
                credentials=credentials,
                credentials_file=client_options.credentials_file,
                host=api_endpoint,
                scopes=client_options.scopes,
                client_cert_source_for_mtls=client_cert_source_func,
                quota_project_id=client_options.quota_project_id,
                client_info=client_info,
                always_use_jwt_access=True,
                api_audience=client_options.api_audience,
            )

    def read_feature_values(
        self,
        request: Union[
            featurestore_online_service.ReadFeatureValuesRequest, dict
        ] = None,
        *,
        entity_type: str = None,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> featurestore_online_service.ReadFeatureValuesResponse:
        r"""Reads Feature values of a specific entity of an
        EntityType. For reading feature values of multiple
        entities of an EntityType, please use
        StreamingReadFeatureValues.

        .. code-block:: python

            # This snippet has been automatically generated and should be regarded as a
            # code template only.
            # It will require modifications to work:
            # - It may require correct/in-range values for request initialization.
            # - It may require specifying regional endpoints when creating the service
            #   client as shown in:
            #   https://googleapis.dev/python/google-api-core/latest/client_options.html
            from google.cloud import aiplatform_v1beta1

            def sample_read_feature_values():
                # Create a client
                client = aiplatform_v1beta1.FeaturestoreOnlineServingServiceClient()

                # Initialize request argument(s)
                feature_selector = aiplatform_v1beta1.FeatureSelector()
                feature_selector.id_matcher.ids = ['ids_value1', 'ids_value2']

                request = aiplatform_v1beta1.ReadFeatureValuesRequest(
                    entity_type="entity_type_value",
                    entity_id="entity_id_value",
                    feature_selector=feature_selector,
                )

                # Make the request
                response = client.read_feature_values(request=request)

                # Handle the response
                print(response)

        Args:
            request (Union[google.cloud.aiplatform_v1beta1.types.ReadFeatureValuesRequest, dict]):
                The request object. Request message for
                [FeaturestoreOnlineServingService.ReadFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreOnlineServingService.ReadFeatureValues].
            entity_type (str):
                Required. The resource name of the EntityType for the
                entity being read. Value format:
                ``projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}``.
                For example, for a machine learning model predicting
                user clicks on a website, an EntityType ID could be
                ``user``.

                This corresponds to the ``entity_type`` field
                on the ``request`` instance; if ``request`` is provided, this
                should not be set.
            retry (google.api_core.retry.Retry): Designation of what errors, if any,
                should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.

        Returns:
            google.cloud.aiplatform_v1beta1.types.ReadFeatureValuesResponse:
                Response message for
                [FeaturestoreOnlineServingService.ReadFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreOnlineServingService.ReadFeatureValues].

        """
        # Create or coerce a protobuf request object.
        # Quick check: If we got a request object, we should *not* have
        # gotten any keyword arguments that map to the request.
        has_flattened_params = any([entity_type])
        if request is not None and has_flattened_params:
            raise ValueError(
                "If the `request` argument is set, then none of "
                "the individual field arguments should be set."
            )

        # Minor optimization to avoid making a copy if the user passes
        # in a featurestore_online_service.ReadFeatureValuesRequest.
        # There's no risk of modifying the input as we've already verified
        # there are no flattened fields.
        if not isinstance(
            request, featurestore_online_service.ReadFeatureValuesRequest
        ):
            request = featurestore_online_service.ReadFeatureValuesRequest(request)
            # If we have keyword arguments corresponding to fields on the
            # request, apply these.
            if entity_type is not None:
                request.entity_type = entity_type

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = self._transport._wrapped_methods[self._transport.read_feature_values]

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata(
                (("entity_type", request.entity_type),)
            ),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def streaming_read_feature_values(
        self,
        request: Union[
            featurestore_online_service.StreamingReadFeatureValuesRequest, dict
        ] = None,
        *,
        entity_type: str = None,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> Iterable[featurestore_online_service.ReadFeatureValuesResponse]:
        r"""Reads Feature values for multiple entities. Depending
        on their size, data for different entities may be broken
        up across multiple responses.

        .. code-block:: python

            # This snippet has been automatically generated and should be regarded as a
            # code template only.
            # It will require modifications to work:
            # - It may require correct/in-range values for request initialization.
            # - It may require specifying regional endpoints when creating the service
            #   client as shown in:
            #   https://googleapis.dev/python/google-api-core/latest/client_options.html
            from google.cloud import aiplatform_v1beta1

            def sample_streaming_read_feature_values():
                # Create a client
                client = aiplatform_v1beta1.FeaturestoreOnlineServingServiceClient()

                # Initialize request argument(s)
                feature_selector = aiplatform_v1beta1.FeatureSelector()
                feature_selector.id_matcher.ids = ['ids_value1', 'ids_value2']

                request = aiplatform_v1beta1.StreamingReadFeatureValuesRequest(
                    entity_type="entity_type_value",
                    entity_ids=['entity_ids_value1', 'entity_ids_value2'],
                    feature_selector=feature_selector,
                )

                # Make the request
                stream = client.streaming_read_feature_values(request=request)

                # Handle the response
                for response in stream:
                    print(response)

        Args:
            request (Union[google.cloud.aiplatform_v1beta1.types.StreamingReadFeatureValuesRequest, dict]):
                The request object. Request message for
                [FeaturestoreOnlineServingService.StreamingFeatureValuesRead][].
            entity_type (str):
                Required. The resource name of the entities' type. Value
                format:
                ``projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}``.
                For example, for a machine learning model predicting
                user clicks on a website, an EntityType ID could be
                ``user``.

                This corresponds to the ``entity_type`` field
                on the ``request`` instance; if ``request`` is provided, this
                should not be set.
            retry (google.api_core.retry.Retry): Designation of what errors, if any,
                should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.

        Returns:
            Iterable[google.cloud.aiplatform_v1beta1.types.ReadFeatureValuesResponse]:
                Response message for
                [FeaturestoreOnlineServingService.ReadFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreOnlineServingService.ReadFeatureValues].

        """
        # Create or coerce a protobuf request object.
        # Quick check: If we got a request object, we should *not* have
        # gotten any keyword arguments that map to the request.
        has_flattened_params = any([entity_type])
        if request is not None and has_flattened_params:
            raise ValueError(
                "If the `request` argument is set, then none of "
                "the individual field arguments should be set."
            )

        # Minor optimization to avoid making a copy if the user passes
        # in a featurestore_online_service.StreamingReadFeatureValuesRequest.
        # There's no risk of modifying the input as we've already verified
        # there are no flattened fields.
        if not isinstance(
            request, featurestore_online_service.StreamingReadFeatureValuesRequest
        ):
            request = featurestore_online_service.StreamingReadFeatureValuesRequest(
                request
            )
            # If we have keyword arguments corresponding to fields on the
            # request, apply these.
            if entity_type is not None:
                request.entity_type = entity_type

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = self._transport._wrapped_methods[
            self._transport.streaming_read_feature_values
        ]

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata(
                (("entity_type", request.entity_type),)
            ),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def write_feature_values(
        self,
        request: Union[
            featurestore_online_service.WriteFeatureValuesRequest, dict
        ] = None,
        *,
        entity_type: str = None,
        payloads: Sequence[
            featurestore_online_service.WriteFeatureValuesPayload
        ] = None,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> featurestore_online_service.WriteFeatureValuesResponse:
        r"""Writes Feature values of one or more entities of an
        EntityType.
        The Feature values are merged into existing entities if
        any. The Feature values to be written must have
        timestamp within the online storage retention.

        .. code-block:: python

            # This snippet has been automatically generated and should be regarded as a
            # code template only.
            # It will require modifications to work:
            # - It may require correct/in-range values for request initialization.
            # - It may require specifying regional endpoints when creating the service
            #   client as shown in:
            #   https://googleapis.dev/python/google-api-core/latest/client_options.html
            from google.cloud import aiplatform_v1beta1

            def sample_write_feature_values():
                # Create a client
                client = aiplatform_v1beta1.FeaturestoreOnlineServingServiceClient()

                # Initialize request argument(s)
                payloads = aiplatform_v1beta1.WriteFeatureValuesPayload()
                payloads.entity_id = "entity_id_value"

                request = aiplatform_v1beta1.WriteFeatureValuesRequest(
                    entity_type="entity_type_value",
                    payloads=payloads,
                )

                # Make the request
                response = client.write_feature_values(request=request)

                # Handle the response
                print(response)

        Args:
            request (Union[google.cloud.aiplatform_v1beta1.types.WriteFeatureValuesRequest, dict]):
                The request object. Request message for
                [FeaturestoreOnlineServingService.WriteFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreOnlineServingService.WriteFeatureValues].
            entity_type (str):
                Required. The resource name of the EntityType for the
                entities being written. Value format:
                ``projects/{project}/locations/{location}/featurestores/ {featurestore}/entityTypes/{entityType}``.
                For example, for a machine learning model predicting
                user clicks on a website, an EntityType ID could be
                ``user``.

                This corresponds to the ``entity_type`` field
                on the ``request`` instance; if ``request`` is provided, this
                should not be set.
            payloads (Sequence[google.cloud.aiplatform_v1beta1.types.WriteFeatureValuesPayload]):
                Required. The entities to be written. Up to 100,000
                feature values can be written across all ``payloads``.

                This corresponds to the ``payloads`` field
                on the ``request`` instance; if ``request`` is provided, this
                should not be set.
            retry (google.api_core.retry.Retry): Designation of what errors, if any,
                should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.

        Returns:
            google.cloud.aiplatform_v1beta1.types.WriteFeatureValuesResponse:
                Response message for
                [FeaturestoreOnlineServingService.WriteFeatureValues][google.cloud.aiplatform.v1beta1.FeaturestoreOnlineServingService.WriteFeatureValues].

        """
        # Create or coerce a protobuf request object.
        # Quick check: If we got a request object, we should *not* have
        # gotten any keyword arguments that map to the request.
        has_flattened_params = any([entity_type, payloads])
        if request is not None and has_flattened_params:
            raise ValueError(
                "If the `request` argument is set, then none of "
                "the individual field arguments should be set."
            )

        # Minor optimization to avoid making a copy if the user passes
        # in a featurestore_online_service.WriteFeatureValuesRequest.
        # There's no risk of modifying the input as we've already verified
        # there are no flattened fields.
        if not isinstance(
            request, featurestore_online_service.WriteFeatureValuesRequest
        ):
            request = featurestore_online_service.WriteFeatureValuesRequest(request)
            # If we have keyword arguments corresponding to fields on the
            # request, apply these.
            if entity_type is not None:
                request.entity_type = entity_type
            if payloads is not None:
                request.payloads = payloads

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = self._transport._wrapped_methods[self._transport.write_feature_values]

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata(
                (("entity_type", request.entity_type),)
            ),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        """Releases underlying transport's resources.

        .. warning::
            ONLY use as a context manager if the transport is NOT shared
            with other clients! Exiting the with block will CLOSE the transport
            and may cause errors in other clients!
        """
        self.transport.close()

    def list_operations(
        self,
        request: operations_pb2.ListOperationsRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> operations_pb2.ListOperationsResponse:
        r"""Lists operations that match the specified filter in the request.

        Args:
            request (:class:`~.operations_pb2.ListOperationsRequest`):
                The request object. Request message for
                `ListOperations` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                    if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.operations_pb2.ListOperationsResponse:
                Response message for ``ListOperations`` method.
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = operations_pb2.ListOperationsRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.list_operations,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def get_operation(
        self,
        request: operations_pb2.GetOperationRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> operations_pb2.Operation:
        r"""Gets the latest state of a long-running operation.

        Args:
            request (:class:`~.operations_pb2.GetOperationRequest`):
                The request object. Request message for
                `GetOperation` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                    if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.operations_pb2.Operation:
                An ``Operation`` object.
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = operations_pb2.GetOperationRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.get_operation,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def delete_operation(
        self,
        request: operations_pb2.DeleteOperationRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> None:
        r"""Deletes a long-running operation.

        This method indicates that the client is no longer interested
        in the operation result. It does not cancel the operation.
        If the server doesn't support this method, it returns
        `google.rpc.Code.UNIMPLEMENTED`.

        Args:
            request (:class:`~.operations_pb2.DeleteOperationRequest`):
                The request object. Request message for
                `DeleteOperation` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                    if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            None
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = operations_pb2.DeleteOperationRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.delete_operation,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

    def cancel_operation(
        self,
        request: operations_pb2.CancelOperationRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> None:
        r"""Starts asynchronous cancellation on a long-running operation.

        The server makes a best effort to cancel the operation, but success
        is not guaranteed.  If the server doesn't support this method, it returns
        `google.rpc.Code.UNIMPLEMENTED`.

        Args:
            request (:class:`~.operations_pb2.CancelOperationRequest`):
                The request object. Request message for
                `CancelOperation` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                    if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            None
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = operations_pb2.CancelOperationRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.cancel_operation,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

    def wait_operation(
        self,
        request: operations_pb2.WaitOperationRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> operations_pb2.Operation:
        r"""Waits until the specified long-running operation is done or reaches at most
        a specified timeout, returning the latest state.

        If the operation is already done, the latest state is immediately returned.
        If the timeout specified is greater than the default HTTP/RPC timeout, the HTTP/RPC
        timeout is used.  If the server does not support this method, it returns
        `google.rpc.Code.UNIMPLEMENTED`.

        Args:
            request (:class:`~.operations_pb2.WaitOperationRequest`):
                The request object. Request message for
                `WaitOperation` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                    if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.operations_pb2.Operation:
                An ``Operation`` object.
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = operations_pb2.WaitOperationRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.wait_operation,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def set_iam_policy(
        self,
        request: iam_policy_pb2.SetIamPolicyRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> policy_pb2.Policy:
        r"""Sets the IAM access control policy on the specified function.

        Replaces any existing policy.

        Args:
            request (:class:`~.iam_policy_pb2.SetIamPolicyRequest`):
                The request object. Request message for `SetIamPolicy`
                method.
            retry (google.api_core.retry.Retry): Designation of what errors, if any,
                should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.policy_pb2.Policy:
                Defines an Identity and Access Management (IAM) policy.
                It is used to specify access control policies for Cloud
                Platform resources.
                A ``Policy`` is a collection of ``bindings``. A
                ``binding`` binds one or more ``members`` to a single
                ``role``. Members can be user accounts, service
                accounts, Google groups, and domains (such as G Suite).
                A ``role`` is a named list of permissions (defined by
                IAM or configured by users). A ``binding`` can
                optionally specify a ``condition``, which is a logic
                expression that further constrains the role binding
                based on attributes about the request and/or target
                resource.

                **JSON Example**

                ::

                    {
                      "bindings": [
                        {
                          "role": "roles/resourcemanager.organizationAdmin",
                          "members": [
                            "user:mike@example.com",
                            "group:admins@example.com",
                            "domain:google.com",
                            "serviceAccount:my-project-id@appspot.gserviceaccount.com"
                          ]
                        },
                        {
                          "role": "roles/resourcemanager.organizationViewer",
                          "members": ["user:eve@example.com"],
                          "condition": {
                            "title": "expirable access",
                            "description": "Does not grant access after Sep 2020",
                            "expression": "request.time <
                            timestamp('2020-10-01T00:00:00.000Z')",
                          }
                        }
                      ]
                    }

                **YAML Example**

                ::

                    bindings:
                    - members:
                      - user:mike@example.com
                      - group:admins@example.com
                      - domain:google.com
                      - serviceAccount:my-project-id@appspot.gserviceaccount.com
                      role: roles/resourcemanager.organizationAdmin
                    - members:
                      - user:eve@example.com
                      role: roles/resourcemanager.organizationViewer
                      condition:
                        title: expirable access
                        description: Does not grant access after Sep 2020
                        expression: request.time < timestamp('2020-10-01T00:00:00.000Z')

                For a description of IAM and its features, see the `IAM
                developer's
                guide <https://cloud.google.com/iam/docs>`__.
        """
        # Create or coerce a protobuf request object.

        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = iam_policy_pb2.SetIamPolicyRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.set_iam_policy,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def get_iam_policy(
        self,
        request: iam_policy_pb2.GetIamPolicyRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> policy_pb2.Policy:
        r"""Gets the IAM access control policy for a function.

        Returns an empty policy if the function exists and does not have a
        policy set.

        Args:
            request (:class:`~.iam_policy_pb2.GetIamPolicyRequest`):
                The request object. Request message for `GetIamPolicy`
                method.
            retry (google.api_core.retry.Retry): Designation of what errors, if
                any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.policy_pb2.Policy:
                Defines an Identity and Access Management (IAM) policy.
                It is used to specify access control policies for Cloud
                Platform resources.
                A ``Policy`` is a collection of ``bindings``. A
                ``binding`` binds one or more ``members`` to a single
                ``role``. Members can be user accounts, service
                accounts, Google groups, and domains (such as G Suite).
                A ``role`` is a named list of permissions (defined by
                IAM or configured by users). A ``binding`` can
                optionally specify a ``condition``, which is a logic
                expression that further constrains the role binding
                based on attributes about the request and/or target
                resource.

                **JSON Example**

                ::

                    {
                      "bindings": [
                        {
                          "role": "roles/resourcemanager.organizationAdmin",
                          "members": [
                            "user:mike@example.com",
                            "group:admins@example.com",
                            "domain:google.com",
                            "serviceAccount:my-project-id@appspot.gserviceaccount.com"
                          ]
                        },
                        {
                          "role": "roles/resourcemanager.organizationViewer",
                          "members": ["user:eve@example.com"],
                          "condition": {
                            "title": "expirable access",
                            "description": "Does not grant access after Sep 2020",
                            "expression": "request.time <
                            timestamp('2020-10-01T00:00:00.000Z')",
                          }
                        }
                      ]
                    }

                **YAML Example**

                ::

                    bindings:
                    - members:
                      - user:mike@example.com
                      - group:admins@example.com
                      - domain:google.com
                      - serviceAccount:my-project-id@appspot.gserviceaccount.com
                      role: roles/resourcemanager.organizationAdmin
                    - members:
                      - user:eve@example.com
                      role: roles/resourcemanager.organizationViewer
                      condition:
                        title: expirable access
                        description: Does not grant access after Sep 2020
                        expression: request.time < timestamp('2020-10-01T00:00:00.000Z')

                For a description of IAM and its features, see the `IAM
                developer's
                guide <https://cloud.google.com/iam/docs>`__.
        """
        # Create or coerce a protobuf request object.

        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = iam_policy_pb2.GetIamPolicyRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.get_iam_policy,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def test_iam_permissions(
        self,
        request: iam_policy_pb2.TestIamPermissionsRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> iam_policy_pb2.TestIamPermissionsResponse:
        r"""Tests the specified IAM permissions against the IAM access control
            policy for a function.

        If the function does not exist, this will return an empty set
        of permissions, not a NOT_FOUND error.

        Args:
            request (:class:`~.iam_policy_pb2.TestIamPermissionsRequest`):
                The request object. Request message for
                `TestIamPermissions` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                 if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.iam_policy_pb2.TestIamPermissionsResponse:
                Response message for ``TestIamPermissions`` method.
        """
        # Create or coerce a protobuf request object.

        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = iam_policy_pb2.TestIamPermissionsRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.test_iam_permissions,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def get_location(
        self,
        request: locations_pb2.GetLocationRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> locations_pb2.Location:
        r"""Gets information about a location.

        Args:
            request (:class:`~.location_pb2.GetLocationRequest`):
                The request object. Request message for
                `GetLocation` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                 if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.location_pb2.Location:
                Location object.
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = locations_pb2.GetLocationRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.get_location,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

    def list_locations(
        self,
        request: locations_pb2.ListLocationsRequest = None,
        *,
        retry: OptionalRetry = gapic_v1.method.DEFAULT,
        timeout: float = None,
        metadata: Sequence[Tuple[str, str]] = (),
    ) -> locations_pb2.ListLocationsResponse:
        r"""Lists information about the supported locations for this service.

        Args:
            request (:class:`~.location_pb2.ListLocationsRequest`):
                The request object. Request message for
                `ListLocations` method.
            retry (google.api_core.retry.Retry): Designation of what errors,
                 if any, should be retried.
            timeout (float): The timeout for this request.
            metadata (Sequence[Tuple[str, str]]): Strings which should be
                sent along with the request as metadata.
        Returns:
            ~.location_pb2.ListLocationsResponse:
                Response message for ``ListLocations`` method.
        """
        # Create or coerce a protobuf request object.
        # The request isn't a proto-plus wrapped type,
        # so it must be constructed via keyword expansion.
        if isinstance(request, dict):
            request = locations_pb2.ListLocationsRequest(**request)

        # Wrap the RPC method; this adds retry and timeout information,
        # and friendly error handling.
        rpc = gapic_v1.method.wrap_method(
            self._transport.list_locations,
            default_timeout=None,
            client_info=DEFAULT_CLIENT_INFO,
        )

        # Certain fields should be provided within the metadata header;
        # add these here.
        metadata = tuple(metadata) + (
            gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
        )

        # Send the request.
        response = rpc(
            request,
            retry=retry,
            timeout=timeout,
            metadata=metadata,
        )

        # Done; return the response.
        return response

try:
    DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
        gapic_version=pkg_resources.get_distribution(
            "google-cloud-aiplatform",
        ).version,
    )
except pkg_resources.DistributionNotFound:
    DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()

__all__ = ("FeaturestoreOnlineServingServiceClient",)


text:
<form class="form-signin" role="form" ng-submit="register()">

Register or sign in

{{registerError.message}}

  <input type="text" class="form-control" placeholder="First Name" ng-model="registration.firstName" required>
  <input type="text" class="form-control" placeholder="Last Name" ng-model="registration.lastName" required>
  <input type="text" class="form-control" placeholder="Email" ng-model="registration.email" required>
  <input type="password" class="form-control" placeholder="Password" ng-model="registration.password" required>
  <input type="password" class="form-control" placeholder="Confrim Password" ng-model="confirmPassword" required>
  <button class="btn btn-lg btn-primary btn-block" type="submit">Register</button>
</form>

redpajama_set_name: RedPajamaGithub


text:
package api

import (
	"errors"
	"testing"

	"github.com/supergiant/supergiant/pkg/core"
	"github.com/supergiant/supergiant/test/fake_core"
	"github.com/supergiant/supergiant/pkg/model"

	. "github.com/smartystreets/goconvey/convey"
)

func TestCloudAccountsList(t *testing.T) {
	srv := newTestServer()
	go srv.Start()
	defer srv.Stop()

	Convey("CloudAccounts List works correctly", t, func() {

		table := []struct {
			// Input
			existingModels []*model.CloudAccount
			// Expectations
			err *model.Error
		}{
			// A successful example
			{
				existingModels: []*model.CloudAccount{
					&model.CloudAccount{
						Name:        "test",
						Provider:    "aws",
						Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
					},
				},
				err: nil,
			},
		}

		for _, item := range table {

			wipeAndInitialize(srv.Core)

			// For ValidateAccount on Create
			srv.Core.AWSProvider = func(_ map[string]string) core.Provider {
				return new(fake_core.Provider)
			}

			requestor := createAdmin(srv.Core)
			sg := srv.Core.APIClient("token", requestor.APIToken)

			for _, existingModel := range item.existingModels {
				srv.Core.CloudAccounts.Create(existingModel)
			}

			list := new(model.CloudAccountList)
			err := sg.CloudAccounts.List(list)

			if item.err == nil {
				So(err, ShouldBeNil)
			} else {
				So(err, ShouldResemble, item.err)
			}

			So(len(list.Items), ShouldEqual, len(item.existingModels))
		}
	})
}

//------------------------------------------------------------------------------

func TestCloudAccountsCreate(t *testing.T) {
	srv := newTestServer()
	go srv.Start()
	defer srv.Stop()

	Convey("CloudAccounts Create works correctly", t, func() {

		table := []struct {
			// Input
			model *model.CloudAccount
			// Mocks
			mockValidateAccountError error
			// Expectations
			err *model.Error
		}{
			// A successful example
			{
				model: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				mockValidateAccountError: nil,
				err: nil,
			},

			// Invalid provider
			{
				model: &model.CloudAccount{
					Name:        "test",
					Provider:    "nocloud",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				mockValidateAccountError: nil,
				err: &model.Error{Status: 422, Message: "Validation failed: Provider: regular expression mismatch"},
			},

			// No name
			{
				model: &model.CloudAccount{
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				mockValidateAccountError: nil,
				err: &model.Error{Status: 422, Message: "Validation failed: Name: zero value"},
			},

			// No credentials
			{
				model: &model.CloudAccount{
					Name:     "test",
					Provider: "aws",
				},
				mockValidateAccountError: nil,
				err: &model.Error{Status: 422, Message: "Validation failed: Credentials: zero value"},
			},

			// On Provider ValidateAccount error
			{
				model: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				mockValidateAccountError: errors.New("creds aren't working"),
				err: &model.Error{Status: 422, Message: "Validation failed: creds aren't working"},
			},
		}

		for _, item := range table {

			wipeAndInitialize(srv.Core)

			srv.Core.AWSProvider = func(_ map[string]string) core.Provider {
				return &fake_core.Provider{
					ValidateAccountFn: func(m *model.CloudAccount) error {
						return item.mockValidateAccountError
					},
				}
			}

			requestor := createAdmin(srv.Core)
			sg := srv.Core.APIClient("token", requestor.APIToken)

			err := sg.CloudAccounts.Create(item.model)

			if item.err == nil {
				So(err, ShouldBeNil)
			} else {
				So(err, ShouldResemble, item.err)
			}
		}
	})
}

//------------------------------------------------------------------------------

func TestCloudAccountsGet(t *testing.T) {
	srv := newTestServer()
	go srv.Start()
	defer srv.Stop()

	Convey("CloudAccounts Get works correctly", t, func() {

		table := []struct {
			// Input
			existingModel *model.CloudAccount
			// Expectations
			err *model.Error
		}{
			// A successful example
			{
				existingModel: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				err: nil,
			},
		}

		for _, item := range table {

			wipeAndInitialize(srv.Core)

			// For ValidateAccount on Create
			srv.Core.AWSProvider = func(_ map[string]string) core.Provider {
				return new(fake_core.Provider)
			}

			requestor := createAdmin(srv.Core)
			sg := srv.Core.APIClient("token", requestor.APIToken)

			srv.Core.CloudAccounts.Create(item.existingModel)

			err := sg.CloudAccounts.Get(item.existingModel.ID, item.existingModel)

			if item.err == nil {
				So(err, ShouldBeNil)
			} else {
				So(err, ShouldResemble, item.err)
			}
		}
	})
}

//------------------------------------------------------------------------------

func TestCloudAccountsUpdate(t *testing.T) {
	srv := newTestServer()
	go srv.Start()
	defer srv.Stop()

	Convey("CloudAccounts Update works correctly", t, func() {

		table := []struct {
			// Input
			existingModel *model.CloudAccount
			modelUpdate   *model.CloudAccount
			// Expectations
			err *model.Error
		}{
			// Can't update Name
			{
				existingModel: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				modelUpdate: &model.CloudAccount{
					Name: "new-name",
				},
				err: &model.Error{Status: 422, Message: "Name cannot be changed"},
			},

			// Can't update Provider
			{
				existingModel: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				modelUpdate: &model.CloudAccount{
					Provider: "do",
				},
				err: &model.Error{Status: 422, Message: "Provider cannot be changed"},
			},

			// Can't update Credentials
			{
				existingModel: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				modelUpdate: &model.CloudAccount{
					Credentials: map[string]string{"new": "credz"},
				},
				err: &model.Error{Status: 422, Message: "Credentials cannot be changed"},
			},
		}

		for _, item := range table {

			wipeAndInitialize(srv.Core)

			// For Create
			srv.Core.AWSProvider = func(_ map[string]string) core.Provider {
				return new(fake_core.Provider)
			}

			requestor := createAdmin(srv.Core)
			sg := srv.Core.APIClient("token", requestor.APIToken)

			srv.Core.CloudAccounts.Create(item.existingModel)

			err := sg.CloudAccounts.Update(item.existingModel.ID, item.modelUpdate)

			if item.err == nil {
				So(err, ShouldBeNil)
			} else {
				So(err, ShouldResemble, item.err)
			}
		}
	})
}

//------------------------------------------------------------------------------

func TestCloudAccountsDelete(t *testing.T) {
	srv := newTestServer()
	go srv.Start()
	defer srv.Stop()

	Convey("CloudAccounts Delete works correctly", t, func() {

		table := []struct {
			// Input
			existingModel    *model.CloudAccount
			hasExistingKubes []*model.Kube
			// Expectations
			err *model.Error
		}{
			// Successful example
			{
				existingModel: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				hasExistingKubes: nil,
				err:              nil,
			},

			// Can't delete if there's Kubes (cuz then we couldn't tear down)
			{
				existingModel: &model.CloudAccount{
					Name:        "test",
					Provider:    "aws",
					Credentials: map[string]string{"access_key": "blah", "secret_key": "bleh"},
				},
				hasExistingKubes: []*model.Kube{
					{
						CloudAccountName: "test",
						Name:             "testkube",
						MasterNodeSize:   "t2.micro",
						NodeSizes:        []string{"t2.micro"},
						AWSConfig: &model.AWSKubeConfig{
							Region:           "us-east-1",
							AvailabilityZone: "us-east-1a",
						},
					},
				},
				err: &model.Error{Status: 422, Message: "Validation failed: Cannot delete CloudAccount that has active Kubes"},
			},
		}

		for _, item := range table {

			wipeAndInitialize(srv.Core)

			// For Create
			srv.Core.AWSProvider = func(_ map[string]string) core.Provider {
				return new(fake_core.Provider)
			}

			requestor := createAdmin(srv.Core)
			sg := srv.Core.APIClient("token", requestor.APIToken)

			srv.Core.CloudAccounts.Create(item.existingModel)

			for _, existingKube := range item.hasExistingKubes {
				srv.Core.Kubes.Create(existingKube)
			}

			err := sg.CloudAccounts.Delete(item.existingModel.ID, item.existingModel)

			if item.err == nil {
				So(err, ShouldBeNil)
			} else {
				So(err, ShouldResemble, item.err)
			}
		}
	})
}


text:
<?php namespace CoandaCMS\ContentSignoff\Repositories;

interface ContentSignoffRepositoryInterface {

    /**
     * @param $version_id
     * @param $version_number
     * @param $page_id
     * @param $page_name
     * @param $requester_id
     * @return mixed
     */
    public function createNewSignoffRequest($version_id, $version_number, $page_id, $page_name, $requester_id);

    /**
     * @param $id
     * @return mixed
     */
    public function getById($id);

    /**
     * @param $per_page
     * @return mixed
     */
    public function pending($per_page);

    /**
     * @param $per_page
     * @return mixed
     */
    public function history($per_page);

}


text:
title: 'App Configuration'
excerpt: 'Learn how to configure a Jovo app and how to add plugins, components, and staging.'
---

# App Configuration

The app configuration in `app.ts` is the place where you can add plugins, components, and other configurations to your Jovo app. [For project related configuration, take a look here](./project-config.md).

## Introduction

The app configuration files are the main entry point of your Jovo apps. Each Jovo project usually comes with at least two files for this:

- `app.ts`: Default configurations
- `app.dev.ts`: Configurations for local development ([FileDb](https://www.jovo.tech/marketplace/db-filedb), [Express server](https://www.jovo.tech/marketplace/server-express) and the [Jovo Debugger](https://www.jovo.tech/docs/debugger))

Jovo offers different [ways to add configurations](#ways-to-add-configurations), [many configuration options](#configuration-elements), and [staging](#staging) that makes it possible to have different Jovo app versions for different deployment environments.

## Ways to add Configurations

There are three ways how app configurations can be done:

- Using the `new App()` constructor in `app.ts` for default configurations.
- Using `app.configure()` for stage-specific configurations.
- Using `app.use()` to add specific plugins and components anywhere in the app.

In the `app.ts`, the configuration is added like this:

```typescript
import { App } from '@jovotech/framework';

// ...

const app = new App({
  // Configuration
});
```

On top of the default configuration, you can add [stages](#staging) with specific options that can be added like this, for example in an `app.dev.ts` file:

```typescript
import { app } from './app';
// ...

app.configure({
  // Configuration
});
```

Both the constructor and `configure()` support the full range of [configuration elements](#configuration-elements).

The third option is the `use()` method. It allows you to add plugins and components anywhere in the app:

```typescript
import { app } from './app';
import { SomePlugin } from './plugin';
// ...

app.use(
  new SomePlugin({
    // Configuration
  }),
);
```

## Configuration Elements

The configuration object that can be passed to both the constructor and the `configure()` method contains [components](#components), [plugins](#plugins), [logging](#logging), and [routing](#routing).

```typescript
{
  components: [
    // ...
  ],
  plugins: [
    // ...
  ],
  logging: {
    // ...
  },
  routing: {
    // ...
  }
}
```

### Components

You can [register root components](./components.md#register-root-components) with your app by adding them to the `components` array:

```typescript
import { GlobalComponent } from './components/GlobalComponent';

// ...

{
  components: [
    GlobalComponent
    // ...
  ],
  // ...
}
```

[Learn more about component registration here](./components.md#register-root-components).

### Plugins

You can add plugins to the `plugins` array like this:

```typescript
import { AlexaPlatform } from '@jovotech/platform-alexa';

// ...

{
  plugins: [
    new AlexaPlatform({
      // Configuration
    })
    // ...
  ],
  // ...
}
```

Each plugin has its own configuration options which you can find in the respective plugin's documentation.

Additionally, each plugin config includes a `skipTests` option that makes sure that [unit tests](https://www.jovo.tech/docs/unit-testing) don't use that plugin:

```typescript
{
  plugins: [
    new SomePlugin({
      // ...
      skipTests: true,
    })
  ],
}
```

You can also access a specific plugin like this:

```typescript
app.plugins.<PluginConstructor>

// Example
app.plugins.SomePlugin
```

This can be helpful if you want to add additional configurations to the default plugin config outside `app.ts`. See [staging](#staging) for more information.

### Logging

[Logging](./logging.md) is enabled by adding the following to the app config:

```typescript
{
  // ...

  logging: true,
}
```

You can also add granular configurations by turning `logging` into an object:

```typescript
{
  // ...

  logging: {
    // ...
  }
}
```

[Learn more about logging and its configuration options here](./logging.md).

### Routing

[Routing](./routing.md) configurations are added to the `routing` object:

```typescript
{
  routing: {
    intentMap: {},
    intentsToSkipUnhandled: [],
  },
  // ...
}
```

#### intentMap

Especially with apps that work across different platforms, it might happen that different platforms use different intent names.

`intentMap` provides a way to map incoming intents to a unified intent that can be used in your [handler routing](./handlers.md#handler-routing-and-the-handle-decorator).

```typescript
{
  routing: {
    intentMap: {
      'AMAZON.HelpIntent': 'HelpIntent',
      // ...
    },
    // ...
  },
  // ...
}
```

For platforms like Alexa that already come with an intent in their requests, the mapped intent name is added to the root of the [`$input` object](./input.md):

```typescript
{
  type: 'INTENT',
  intent: 'HelpIntent',
}
```

If you're using an [NLU integration](./nlu.md), the original intent stays in the `nlu` property and the mapped intent is added to the root of `$input`:

```typescript
{
  type: 'TEXT',
  text: 'My name is Max',
  nlu: {
    intent: 'MyNameIsIntent',
    entities: {
      name: {
        value: 'Max',
      },
    },
  },
  intent: 'MappedMyNameIsIntent',
}
```

#### intentsToSkipUnhandled

`intentsToSkipUnhandled` includes all intents that shouldn't be fulfilled by an [`UNHANDLED` handler](./handlers.md#unhandled).

```typescript
{
  routing: {
    intentsToSkipUnhandled: [
      'HelpIntent'
    ],
    // ...
  },
  // ...
}
```

[Learn more about `intentsToSkipUnhandled` here](./routing.md#intentstoskipunhadled).

## Staging

Stage-specific configurations from a file called `app.<stage>.ts` get merged into the default configuration from `app.ts`.

For example, most Jovo projects include an `app.dev.ts` file that comes with specific configuration for local development ([FileDb](https://www.jovo.tech/marketplace/db-filedb), [Express server](https://www.jovo.tech/marketplace/server-express) and the [Jovo Debugger](https://www.jovo.tech/docs/debugger)).

You can create a new stage like this:

```sh
$ jovo new:stage <stage>

# Example that creates a new app.prod.ts file
$ jovo new:stage prod
```

This creates a new file `app.prod.ts`. In the process, you can select plugins and a server integration to work with this stage.

Typically, a stage app config uses the `configure()` method to modify the configuration.

```typescript
import { app } from './app';
// ...

app.configure({
  // Configuration
});
```

It is also possible to reference a plugin from the default configuration in `app.ts` and add plugins to it using the `use()` method.

Here is an example for [Dashbot Analytics](https://www.jovo.tech/marketplace/analytics-dashbot) being added to [Alexa](https://www.jovo.tech/marketplace/platform) in `app.prod.ts`:

```typescript
import { app } from './app';
import { DashbotAnalytics } from '@jovotech/analytics-dashbot';
// ...

app.plugins.AlexaPlatform.use(new DashbotAnalytics({ apiKey: '<yourApiKey>' }));
```


text:
class Trigger < ActiveRecord::Base
  belongs_to :pending_item, :polymorphic => true

  class << self
    def post_action(due_at, item, method='came_due')
      create!(:due_at => due_at, :pending_item => item,
              :trigger_method => method)
      fire
    end

    def fire
      begin
        destroy_all ['due_at <= ?', Time.now]
        true
      rescue
        migrator = Migrator.new

        if !migrator.pending_migrations.empty?
          starting_version = migrator.current_schema_version
          migrator.migrate

          if starting_version == 0
            load "#{Rails.root}/Rakefile"
            Rake::Task['db:seed'].invoke
            User.reset_column_information
            Article.reset_column_information
            Page.reset_column_information
          end
        end
      end
    end

    def remove(pending_item, conditions = { })
      return if pending_item.new_record?
      conditions = conditions.merge(pending_item_id: pending_item.id,
                                    pending_item_type: pending_item.class.to_s)
      where(conditions).delete_all
    end
  end

  before_destroy :trigger_pending_item

  def trigger_pending_item
    pending_item.send(trigger_method) if pending_item
    return true
  end
end


text:
{{cookiecutter.app_name}}
=========================

An application built on top of Universal Core's Springboard.


text:
package org.scala_tools.javautils.j2s

import java.util.Enumeration
import scala.{Iterator => SIterator}
import org.scala_tools.javautils.s2j.SEnumerationWrapper

class RichJEnumeration[T](enumeration: Enumeration[T]) {
  def foreach(fn: T => Unit): Unit =
    while (enumeration.hasMoreElements)
      fn(enumeration.nextElement)

  def asScala: SIterator[T] = enumeration match {
    case ew: SEnumerationWrapper[_] =>
      ew.asScala.asInstanceOf[SIterator[T]]
    case _ => new JEnumerationWrapper[T] {
      type Wrapped = Enumeration[T]
      val underlying = enumeration
    }
  }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CacheEmulator
{
	class CacheChunck
	{

	}
	class Cache
	{
		CacheChunck Chuncks;
	}

	interface IEmulator
	{

	}
}


text:
import pytest
import asyncio
from http import client
from unittest import mock

from waterbutler.core import exceptions
from waterbutler.core.path import WaterButlerPath
from waterbutler.server.api.v1.provider.create import CreateMixin

from tests.utils import MockCoroutine

class BaseCreateMixinTest:

    def setup_method(self, method):
        self.mixin = CreateMixin()
        self.mixin.write = mock.Mock()
        self.mixin.request = mock.Mock()
        self.mixin.set_status = mock.Mock()
        self.mixin.get_query_argument = mock.Mock()

class TestValidatePut(BaseCreateMixinTest):

    def test_invalid_kind(self):
        self.mixin.get_query_argument.return_value = 'notaferlder'

        with pytest.raises(exceptions.InvalidParameters) as e:
            self.mixin.prevalidate_put()

        assert e.value.message == 'Kind must be file, folder or unspecified (interpreted as file), not notaferlder'

    def test_default_kind(self):
        self.mixin.path = '/'
        self.mixin.get_query_argument.return_value = 'file'
        self.mixin.request.headers.get.side_effect = Exception('Breakout')

        with pytest.raises(Exception) as e:
            self.mixin.prevalidate_put()

        assert self.mixin.kind == 'file'
        assert e.value.args == ('Breakout', )
        assert self.mixin.get_query_argument.has_call(mock.call('kind', default='file'))

    def test_length_required_for_files(self):
        self.mixin.path = '/'
        self.mixin.request.headers = {}
        self.mixin.get_query_argument.return_value = 'file'

        with pytest.raises(exceptions.InvalidParameters) as e:
            self.mixin.prevalidate_put()

        assert e.value.code == client.LENGTH_REQUIRED
        assert e.value.message == 'Content-Length is required for file uploads'

    def test_payload_with_folder(self):
        self.mixin.path = '/'
        self.mixin.request.headers = {'Content-Length': 5000}
        self.mixin.get_query_argument.return_value = 'folder'

        with pytest.raises(exceptions.InvalidParameters) as e:
            self.mixin.prevalidate_put()

        assert e.value.code == client.REQUEST_ENTITY_TOO_LARGE
        assert e.value.message == 'Folder creation requests may not have a body'

        self.mixin.request.headers = {'Content-Length': 'notanumber'}
        self.mixin.get_query_argument.return_value = 'file'

        with pytest.raises(exceptions.InvalidParameters) as e:
            self.mixin.prevalidate_put()

        assert e.value.code == client.BAD_REQUEST
        assert e.value.message == 'Invalid Content-Length'

    @pytest.mark.asyncio
    async def test_name_required_for_dir(self):
        self.mixin.path = WaterButlerPath('/', folder=True)
        self.mixin.get_query_argument.return_value = None

        with pytest.raises(exceptions.InvalidParameters) as e:
            await self.mixin.postvalidate_put()

        assert e.value.message == 'Missing required parameter \'name\''

    @pytest.mark.asyncio
    async def test_name_refused_for_file(self):
        self.mixin.path = WaterButlerPath('/foo.txt', folder=False)
        self.mixin.get_query_argument.return_value = 'bar.txt'

        with pytest.raises(exceptions.InvalidParameters) as e:
            await self.mixin.postvalidate_put()

        assert e.value.message == "'name' parameter doesn't apply to actions on files"

    @pytest.mark.asyncio
    async def test_kind_must_be_folder(self):
        self.mixin.path = WaterButlerPath('/adlkjf')
        self.mixin.get_query_argument.return_value = None
        self.mixin.kind = 'folder'

        with pytest.raises(exceptions.InvalidParameters) as e:
            await self.mixin.postvalidate_put()

        assert e.value.message == 'Path must be a folder (and end with a "/") if trying to create a subfolder'
        assert e.value.code == client.CONFLICT

class TestCreateFolder(BaseCreateMixinTest):

    @pytest.mark.asyncio
    async def test_created(self):
        metadata = mock.Mock()
        self.mixin.path = '/'
        self.mixin.resource = '3rqws'
        metadata.json_api_serialized.return_value = {'day': 'tum'}
        self.mixin.provider = mock.Mock(
            create_folder=MockCoroutine(return_value=metadata)
        )
        target = WaterButlerPath('/apath/')
        self.mixin.target_path = target

        await self.mixin.create_folder()

        assert self.mixin.set_status.assert_called_once_with(201) is None
        assert self.mixin.write.assert_called_once_with({'data': {'day': 'tum'}}) is None
        assert self.mixin.provider.create_folder.assert_called_once_with(target) is None

class TestUploadFile(BaseCreateMixinTest):

    def setup_method(self, method):
        super().setup_method(method)
        self.mixin.wsock = mock.Mock()
        self.mixin.writer = mock.Mock()

    @pytest.mark.asyncio
    async def test_created(self):
        metadata = mock.Mock()
        self.mixin.resource = '3rqws'
        self.mixin.uploader = asyncio.Future()
        metadata.json_api_serialized.return_value = {'day': 'tum'}
        self.mixin.uploader.set_result((metadata, True))

        await self.mixin.upload_file()

        assert self.mixin.wsock.close.called
        assert self.mixin.writer.close.called
        assert self.mixin.set_status.assert_called_once_with(201) is None
        assert self.mixin.write.assert_called_once_with({'data': {'day': 'tum'}}) is None

    @pytest.mark.asyncio
    async def test_not_created(self):
        metadata = mock.Mock()
        self.mixin.resource = '3rqws'
        self.mixin.uploader = asyncio.Future()
        metadata.json_api_serialized.return_value = {'day': 'ta'}
        self.mixin.uploader.set_result((metadata, False))

        await self.mixin.upload_file()

        assert self.mixin.wsock.close.called
        assert self.mixin.writer.close.called
        assert self.mixin.set_status.called is False
        assert self.mixin.write.assert_called_once_with({'data': {'day': 'ta'}}) is None


text:
package org.sonatype.flexmojos.generator.iface;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.ws.jaxme.js.JavaQName;
import org.apache.ws.jaxme.js.JavaQNameImpl;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.JavaSourceFactory;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.sonatype.flexmojos.generator.GenerationException;
import org.sonatype.flexmojos.generator.GenerationRequest;
import org.sonatype.flexmojos.generator.Generator;

import flex2.compiler.config.ConfigurationInfo;
import flex2.compiler.config.ConfigurationValue;

@Component( role = Generator.class, hint = "internal-ifaces" )
public final class InternalIFacesGenerator
    extends AbstractLogEnabled
    implements Generator
{

    private static final String PACKAGE = "org.sonatype.flexmojos.compiler";

    private static final String CFG_PREFIX = "cfg";

    private static final String GET_PREFIX = "get";

    private static final String CONFIGURATION_SUFFIX = "Configuration";

    private static final String INFO_SUFFIX = "Info";

    public InternalIFacesGenerator()
    {
    }

    public void generate( GenerationRequest request )
        throws GenerationException
    {
        JavaSourceFactory factory = new JavaSourceFactory();

        JavaQName ann = JavaQNameImpl.getInstance( PACKAGE, "IFlexConfiguration" );
        JavaSource annSource = factory.newJavaSource( ann, "public" );
        annSource.setType( JavaSource.INTERFACE );

        JavaQName arg = JavaQNameImpl.getInstance( PACKAGE, "IFlexArgument" );
        JavaSource argSource = factory.newJavaSource( arg, "public" );
        argSource.setType( JavaSource.INTERFACE );

        for ( String classname : request.getClasses().keySet() )
        {
            Class<?> clazz;
            try
            {
                clazz = request.getClassLoader().loadClass( classname );
            }
            catch ( ClassNotFoundException e )
            {
                throw new GenerationException( e.getMessage(), e );
            }

            getMethods( clazz, factory, ann, arg );

            File outDir = request.getTransientOutputFolder();
            outDir.mkdirs();

            try
            {
                factory.write( outDir );
            }
            catch ( Exception e )
            {
                throw new GenerationException( "Error generating " + clazz.getName(), e );
            }
        }
    }

    private String varname( String membername, String basename )
    {
        return ( ( basename == null ) ? membername : ( basename + "." + membername ) );
    }

    private JavaQName getMethods( Class<?> clazz, JavaSourceFactory factory, JavaQName ann, JavaQName arg )
        throws GenerationException
    {
        JavaQName className = JavaQNameImpl.getInstance( PACKAGE, "I" + clazz.getSimpleName() );
        if ( factory.getJavaSource( className ) != null )
        {
            return className;
        }

        JavaSource js = factory.newJavaSource( className, "public" );
        js.setType( JavaSource.INTERFACE );
        js.addExtends( ann );

        Method methods[] = clazz.getMethods();

        for ( int m = 0; m < methods.length; ++m )
        {
            Method method = methods[m];

            if ( method.getName().startsWith( CFG_PREFIX ) )
            {
                Class<?>[] pt = method.getParameterTypes();

                if ( ( pt.length > 1 )
                    && ( pt[0].getCanonicalName().equals( ConfigurationValue.class.getCanonicalName() ) ) )
                {
                    // This is an autoconfiguration setter!

                    ConfigurationInfo info = createInfo( method );

                    String leafname = method.getName().substring( CFG_PREFIX.length() );
                    String name = varname( leafname, null );

                    JavaQName type;
                    int args = info.getArgCount();
                    if ( args == 0 )
                    {
                        continue;
                    }
                    else if ( "RuntimeSharedLibraryPath".equals( name ) )
                    {
                        type = generateSubclass( factory, arg, info, name, 2, String.class, Map.class );
                    }
                    else if ( "Extension".equals( name ) )
                    {
                        type = generateSubclass( factory, arg, info, name, 2, File.class, String[].class );
                    }
                    else if ( "Frame".equals( name ) )
                    {
                        type = generateSubclass( factory, arg, info, name, 2, String.class, String[].class );
                    }
                    else if ( args == 1 )
                    {
                        type = JavaQNameImpl.getInstance( getArgType( info, 0 ) );
                    }
                    else if ( args < 0 )
                    {
                        Object argnames;
                        try
                        {
                            Field f = ConfigurationInfo.class.getDeclaredField( "argnames" );
                            f.setAccessible( true );
                            argnames = f.get( info );
                        }
                        catch ( Exception e )
                        {
                            throw new GenerationException( e.getMessage(), e );
                        }
                        if ( argnames != null && argnames.getClass().isArray() && ( (Object[]) argnames ).length != 1 )
                        {
                            type = generateSubclass( factory, arg, info, name, ( (Object[]) argnames ).length );
                        }
                        else
                        {
                            type = JavaQNameImpl.getInstance( method.getParameterTypes()[1] );
                        }
                    }
                    else
                    {
                        type = generateSubclass( factory, arg, info, name, args );
                    }

                    if ( info.isPath() && args <= 1 )
                    {
                        type = JavaQNameImpl.getInstance( File.class );
                    }

                    type = promoteWrappers( type );

                    if ( info.allowMultiple()
                        && !( type.isArray() || type.equals( JavaQNameImpl.getInstance( List.class ) ) ) )
                    {
                        type = JavaQNameImpl.getArray( type );
                    }

                    /*JavaMethod nm =*/ js.newJavaMethod( GET_PREFIX + name, type );
                }
            }
        }

        // Now find all children.
        for ( int m = 0; m < methods.length; ++m )
        {
            Method method = methods[m];

            String name = method.getName();
            if ( name.startsWith( GET_PREFIX ) && name.endsWith( CONFIGURATION_SUFFIX ) )
            {
                JavaQName source = getMethods( method.getReturnType(), factory, ann, arg );
                js.newJavaMethod( name, source );
            }
            else
            {
                continue;
            }
        }

        return className;
    }

    private JavaQName generateSubclass( JavaSourceFactory factory, JavaQName arg, ConfigurationInfo info, String name,
                                        int args, Class<?>... typeClasses )
    {
        JavaQName type;
        type = JavaQNameImpl.getInstance( PACKAGE, "I" + name );

        if ( factory.getJavaSource( type ) == null )
        {
            JavaSource subClass = factory.newJavaSource( type, "public" );
            subClass.setType( JavaSource.INTERFACE );
            subClass.addExtends( arg );

            StringBuilder order = new StringBuilder();
            order.append( "  String[] ORDER = new String[] {" );
            for ( int i = 0; i < args; i++ )
            {
                Class<?> argType = getArgType( info, i, typeClasses );
                String argName = info.getArgName( i );
                argName = StringUtil.toCamelCase( argName );
                subClass.newJavaMethod( argName, argType );

                order.append( '"' ).append( argName ).append( '"' ).append( ", " );
            }
            order.append( " };" );

            subClass.addRawJavaSource( order.toString() );
        }
        return type;
    }

    private JavaQName promoteWrappers( JavaQName type )
        throws GenerationException
    {
        if ( !type.isPrimitive() )
        {
            return type;
        }

        if ( JavaQNameImpl.BOOLEAN.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Boolean.class );
        }
        else if ( JavaQNameImpl.BYTE.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Byte.class );
        }
        else if ( JavaQNameImpl.CHAR.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Character.class );
        }
        else if ( JavaQNameImpl.DOUBLE.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Double.class );
        }
        else if ( JavaQNameImpl.FLOAT.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Float.class );
        }
        else if ( JavaQNameImpl.INT.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Integer.class );
        }
        else if ( JavaQNameImpl.LONG.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Long.class );
        }
        else if ( JavaQNameImpl.SHORT.equals( type ) )
        {
            return JavaQNameImpl.getInstance( Short.class );
        }
        else
        {
            throw new GenerationException( "Invalid primitive type: " + type );
        }
    }

    private Class<?> getArgType( ConfigurationInfo info, int i, Class<?>... typeClasses )
    {
        if ( typeClasses != null && i <= typeClasses.length - 1 )
        {
            return typeClasses[i];
        }

        Class<?> argType;
        try
        {
            argType = info.getArgType( i );
        }
        catch ( NullPointerException e )
        {
            argType = String.class;
        }
        return argType;
    }

    private static ConfigurationInfo createInfo( Method setterMethod )
        throws GenerationException
    {
        ConfigurationInfo info = null;

        String infoMethodName = GET_PREFIX + setterMethod.getName().substring( CFG_PREFIX.length() ) + INFO_SUFFIX;
        Class<?> cfgClass = setterMethod.getDeclaringClass();

        try
        {
            Method infoMethod = cfgClass.getMethod( infoMethodName );

            if ( !Modifier.isStatic( infoMethod.getModifiers() ) )
            {
                assert false : ( "coding error: " + cfgClass.getName() + "." + infoMethodName + " needs to be static!" );
                infoMethod = null;
            }

            info = (ConfigurationInfo) infoMethod.invoke( null );

        }
        catch ( NoSuchMethodException e )
        {
            // use default configuration
            info = new ConfigurationInfo();
        }
        catch ( Exception e )
        {
            System.out.println( Arrays.toString( cfgClass.getMethods() ) );
            throw new GenerationException( e.getMessage(), e );
        }

        // info.setSetterMethod( setterMethod );
        // info.setGetterMethod( getterMethod );

        return info;
    }

}