# coding: utf-8

"""
    LUSID API

    FINBOURNE Technology  # noqa: E501

    Contact: info@finbourne.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from datetime import datetime
from typing import Any, Dict, Optional
from pydantic.v1 import BaseModel, Field, StrictStr, constr, validator
from lusid.models.dependency_source_filter import DependencySourceFilter

class MarketDataSpecificRule(BaseModel):
    """
    Extends market data key rules to be able to catch dependencies depending on where the dependency comes from, as opposed to what the dependency is asking for.  For example, a market data rule might instruct all rates curves to be retrieved from a particular scope.  This class gives the ability to set different behaviour depending on what is requesting the rates curve.  Using two specific rules, one could instruct rates curves requested by bonds to be retrieved from a different scope than rates curves requested by swaps.  # noqa: E501
    """
    key: constr(strict=True, max_length=128, min_length=0) = Field(..., description="The market data key pattern which this is a rule for. A dot separated string (A.B.C.D.*)")
    supplier: constr(strict=True, max_length=32, min_length=0) = Field(..., description="The market data supplier (where the data comes from)")
    data_scope: constr(strict=True, max_length=256, min_length=1) = Field(..., alias="dataScope", description="The scope in which the data should be found when using this rule.")
    quote_type: StrictStr = Field(..., alias="quoteType", description="The available values are: Price, Spread, Rate, LogNormalVol, NormalVol, ParSpread, IsdaSpread, Upfront, Index, Ratio, Delta, PoolFactor, InflationAssumption, DirtyPrice")
    field: constr(strict=True, max_length=32, min_length=0) = Field(..., description="The conceptual qualification for the field, such as bid, mid, or ask.  The field must be one of a defined set for the given supplier, in the same way as it  is for the Finbourne.WebApi.Interface.Dto.Quotes.QuoteSeriesId")
    quote_interval: Optional[constr(strict=True, max_length=16, min_length=0)] = Field(None, alias="quoteInterval", description="Shorthand for the time interval used to select market data. This must be a dot-separated string              nominating a start and end date, for example '5D.0D' to look back 5 days from today (0 days ago). The syntax              is <i>int</i><i>char</i>.<i>int</i><i>char</i>, where <i>char</i> is one of D(ay), W(eek), M(onth) or Y(ear).")
    as_at: Optional[datetime] = Field(None, alias="asAt", description="The AsAt predicate specification.")
    price_source: Optional[constr(strict=True, max_length=256, min_length=0)] = Field(None, alias="priceSource", description="The source of the quote. For a given provider/supplier of market data there may be an additional qualifier, e.g. the exchange or bank that provided the quote")
    mask: Optional[constr(strict=True, max_length=256, min_length=0)] = Field(None, description="Allows for partial or complete override of the market asset resolved for a dependency  Either a named override or a dot separated string (A.B.C.D.*).  e.g. for Rates curve 'EUR.*' will replace the resolve MarketAsset 'GBP/12M', 'GBP/3M' with the EUR equivalent, if there  are no wildcards in the mask, the mask is taken as the MarketAsset for any dependency matching the rule.")
    dependency_source_filter: DependencySourceFilter = Field(..., alias="dependencySourceFilter")
    source_system: Optional[constr(strict=True, max_length=256, min_length=0)] = Field(None, alias="sourceSystem", description="Determines from where LUSID should attempt to find the data. Optional and, if omitted, will default to \"Lusid\".  This means that data will be retrieved from the Quotes store and the ComplexMarketData store.  These can be populated using the Quotes and ComplexMarketData endpoints.")
    __properties = ["key", "supplier", "dataScope", "quoteType", "field", "quoteInterval", "asAt", "priceSource", "mask", "dependencySourceFilter", "sourceSystem"]

    @validator('data_scope')
    def data_scope_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if not re.match(r"^[a-zA-Z0-9\-_]+$", value):
            raise ValueError(r"must validate the regular expression /^[a-zA-Z0-9\-_]+$/")
        return value

    @validator('quote_type')
    def quote_type_validate_enum(cls, value):
        """Validates the enum"""
        if value not in ('Price', 'Spread', 'Rate', 'LogNormalVol', 'NormalVol', 'ParSpread', 'IsdaSpread', 'Upfront', 'Index', 'Ratio', 'Delta', 'PoolFactor', 'InflationAssumption', 'DirtyPrice'):
            raise ValueError("must be one of enum values ('Price', 'Spread', 'Rate', 'LogNormalVol', 'NormalVol', 'ParSpread', 'IsdaSpread', 'Upfront', 'Index', 'Ratio', 'Delta', 'PoolFactor', 'InflationAssumption', 'DirtyPrice')")
        return value

    class Config:
        """Pydantic configuration"""
        allow_population_by_field_name = True
        validate_assignment = True

    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.dict(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> MarketDataSpecificRule:
        """Create an instance of MarketDataSpecificRule from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self):
        """Returns the dictionary representation of the model using alias"""
        _dict = self.dict(by_alias=True,
                          exclude={
                          },
                          exclude_none=True)
        # override the default output from pydantic by calling `to_dict()` of dependency_source_filter
        if self.dependency_source_filter:
            _dict['dependencySourceFilter'] = self.dependency_source_filter.to_dict()
        # set to None if quote_interval (nullable) is None
        # and __fields_set__ contains the field
        if self.quote_interval is None and "quote_interval" in self.__fields_set__:
            _dict['quoteInterval'] = None

        # set to None if as_at (nullable) is None
        # and __fields_set__ contains the field
        if self.as_at is None and "as_at" in self.__fields_set__:
            _dict['asAt'] = None

        # set to None if price_source (nullable) is None
        # and __fields_set__ contains the field
        if self.price_source is None and "price_source" in self.__fields_set__:
            _dict['priceSource'] = None

        # set to None if mask (nullable) is None
        # and __fields_set__ contains the field
        if self.mask is None and "mask" in self.__fields_set__:
            _dict['mask'] = None

        # set to None if source_system (nullable) is None
        # and __fields_set__ contains the field
        if self.source_system is None and "source_system" in self.__fields_set__:
            _dict['sourceSystem'] = None

        return _dict

    @classmethod
    def from_dict(cls, obj: dict) -> MarketDataSpecificRule:
        """Create an instance of MarketDataSpecificRule from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return MarketDataSpecificRule.parse_obj(obj)

        _obj = MarketDataSpecificRule.parse_obj({
            "key": obj.get("key"),
            "supplier": obj.get("supplier"),
            "data_scope": obj.get("dataScope"),
            "quote_type": obj.get("quoteType"),
            "field": obj.get("field"),
            "quote_interval": obj.get("quoteInterval"),
            "as_at": obj.get("asAt"),
            "price_source": obj.get("priceSource"),
            "mask": obj.get("mask"),
            "dependency_source_filter": DependencySourceFilter.from_dict(obj.get("dependencySourceFilter")) if obj.get("dependencySourceFilter") is not None else None,
            "source_system": obj.get("sourceSystem")
        })
        return _obj
