# Auto generated from None by pythongen.py version: 0.9.0
# Generation date:
# Schema: synopsis2
#
# id: http://example.org/sample/example1
# description:
# license:

import dataclasses
import sys
import re
from typing import Optional, List, Union, Dict, ClassVar, Any
from dataclasses import dataclass
from biolinkml.meta import EnumDefinition, PermissibleValue, PvFormulaOptions

from biolinkml.utils.slot import Slot
from biolinkml.utils.metamodelcore import empty_list, empty_dict, bnode
from biolinkml.utils.yamlutils import YAMLRoot, extended_str, extended_float, extended_int
if sys.version_info < (3, 7, 6):
    from biolinkml.utils.dataclass_extensions_375 import dataclasses_init_fn_with_kwargs
else:
    from biolinkml.utils.dataclass_extensions_376 import dataclasses_init_fn_with_kwargs
from biolinkml.utils.formatutils import camelcase, underscore, sfx
from biolinkml.utils.enumerations import EnumDefinitionImpl
from rdflib import Namespace, URIRef
from biolinkml.utils.curienamespace import CurieNamespace
from biolinkml.utils.metamodelcore import Bool

metamodel_version = "1.7.0"

# Overwrite dataclasses _init_fn to add **kwargs in __init__
dataclasses._init_fn = dataclasses_init_fn_with_kwargs

# Namespaces
EX = CurieNamespace('ex', 'http://example.org/model/')
FOAF = CurieNamespace('foaf', 'http://xmlns.com/foaf/0.1/')
XSD = CurieNamespace('xsd', 'http://www.w3.org/2001/XMLSchema#')
DEFAULT_ = EX


# Types
class String(str):
    type_class_uri = XSD.string
    type_class_curie = "xsd:string"
    type_name = "string"
    type_model_uri = EX.String


class Int(int):
    type_class_uri = XSD.integer
    type_class_curie = "xsd:integer"
    type_name = "int"
    type_model_uri = EX.Int


class Boolean(Bool):
    type_class_uri = XSD.boolean
    type_class_curie = "xsd:boolean"
    type_name = "boolean"
    type_model_uri = EX.Boolean


# Class references
class PersonId(extended_str):
    pass


class FriendlyPersonId(PersonId):
    pass


@dataclass
class Person(YAMLRoot):
    """
    A person, living or dead
    """
    _inherited_slots: ClassVar[List[str]] = []

    class_class_uri: ClassVar[URIRef] = EX.Person
    class_class_curie: ClassVar[str] = "ex:Person"
    class_name: ClassVar[str] = "person"
    class_model_uri: ClassVar[URIRef] = EX.Person

    id: Union[str, PersonId] = None
    last_name: str = None
    first_name: Optional[Union[str, List[str]]] = empty_list()
    age: Optional[int] = None
    living: Optional[Bool] = None
    knows: Optional[Union[Union[str, PersonId], List[Union[str, PersonId]]]] = empty_list()

    def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
        if self.id is None:
            raise ValueError("id must be supplied")
        if not isinstance(self.id, PersonId):
            self.id = PersonId(self.id)

        if self.last_name is None:
            raise ValueError("last_name must be supplied")
        if not isinstance(self.last_name, str):
            self.last_name = str(self.last_name)

        if self.first_name is None:
            self.first_name = []
        if not isinstance(self.first_name, list):
            self.first_name = [self.first_name]
        self.first_name = [v if isinstance(v, str) else str(v) for v in self.first_name]

        if self.age is not None and not isinstance(self.age, int):
            self.age = int(self.age)

        if self.living is not None and not isinstance(self.living, Bool):
            self.living = Bool(self.living)

        if self.knows is None:
            self.knows = []
        if not isinstance(self.knows, list):
            self.knows = [self.knows]
        self.knows = [v if isinstance(v, PersonId) else PersonId(v) for v in self.knows]

        super().__post_init__(**kwargs)


@dataclass
class FriendlyPerson(Person):
    """
    Any person that knows someone
    """
    _inherited_slots: ClassVar[List[str]] = []

    class_class_uri: ClassVar[URIRef] = EX.FriendlyPerson
    class_class_curie: ClassVar[str] = "ex:FriendlyPerson"
    class_name: ClassVar[str] = "friendly_person"
    class_model_uri: ClassVar[URIRef] = EX.FriendlyPerson

    id: Union[str, FriendlyPersonId] = None
    last_name: str = None
    knows: Union[Union[str, PersonId], List[Union[str, PersonId]]] = None

    def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
        if self.id is None:
            raise ValueError("id must be supplied")
        if not isinstance(self.id, FriendlyPersonId):
            self.id = FriendlyPersonId(self.id)

        if self.knows is None:
            raise ValueError("knows must be supplied")
        elif not isinstance(self.knows, list):
            self.knows = [self.knows]
        elif len(self.knows) == 0:
            raise ValueError(f"knows must be a non-empty list")
        self.knows = [v if isinstance(v, PersonId) else PersonId(v) for v in self.knows]

        super().__post_init__(**kwargs)


# Enumerations


# Slots
class slots:
    pass

slots.id = Slot(uri=EX.id, name="id", curie=EX.curie('id'),
                   model_uri=EX.id, domain=None, range=URIRef)

slots.first_name = Slot(uri=FOAF.firstName, name="first name", curie=FOAF.curie('firstName'),
                   model_uri=EX.first_name, domain=None, range=Optional[Union[str, List[str]]])

slots.last_name = Slot(uri=FOAF.lastName, name="last name", curie=FOAF.curie('lastName'),
                   model_uri=EX.last_name, domain=None, range=str)

slots.living = Slot(uri=EX.living, name="living", curie=EX.curie('living'),
                   model_uri=EX.living, domain=None, range=Optional[Bool])

slots.age = Slot(uri=FOAF.age, name="age", curie=FOAF.curie('age'),
                   model_uri=EX.age, domain=None, range=Optional[int])

slots.knows = Slot(uri=FOAF.knows, name="knows", curie=FOAF.curie('knows'),
                   model_uri=EX.knows, domain=None, range=Optional[Union[Union[str, PersonId], List[Union[str, PersonId]]]])

slots.friendly_person_knows = Slot(uri=EX.knows, name="friendly_person_knows", curie=EX.curie('knows'),
                   model_uri=EX.friendly_person_knows, domain=FriendlyPerson, range=Union[Union[str, PersonId], List[Union[str, PersonId]]])
<img src="http://yuml.me/diagram/nofunky;dir:TB/class/[Person]<knows 0..*- [Person|id:string;first_name:string *;last_name:string;age:int %3F;living:boolean %3F],[FriendlyPerson|id(i):string;first_name(i):string *;last_name(i):string;age(i):int %3F;living(i):boolean %3F]- knows 1..*>[Person],[Person]^-[FriendlyPerson],[FriendlyPerson]"/>

-----
http://yuml.me/diagram/nofunky;dir:TB/class/[Person]<knows 0..*- [Person|id:string;first_name:string *;last_name:string;age:int %3F;living:boolean %3F],[FriendlyPerson|id(i):string;first_name(i):string *;last_name(i):string;age(i):int %3F;living(i):boolean %3F]- knows 1..*>[Person],[Person]^-[FriendlyPerson],[FriendlyPerson]

{
   "_comments": "Auto generated from None by jsonldcontextgen.py version: 0.1.1\nGeneration date:",
   "@context": {
      "type": "@type",
      "ex": "http://example.org/model/",
      "foaf": "http://xmlns.com/foaf/0.1/",
      "xsd": "http://www.w3.org/2001/XMLSchema#",
      "@vocab": "http://example.org/model/",
      "age": {
         "@type": "xsd:integer",
         "@id": "foaf:age"
      },
      "first_name": {
         "@id": "foaf:firstName"
      },
      "id": "@id",
      "knows": {
         "@type": "@id",
         "@id": "foaf:knows"
      },
      "last_name": {
         "@id": "foaf:lastName"
      },
      "living": {
         "@type": "xsd:boolean"
      },
      "@base": "http://example.org/context/"
   }
}
BASE <http://example.org/model/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>


<String> xsd:string

<Int> xsd:integer

<Boolean> xsd:boolean

<FriendlyPerson> CLOSED {
    (  $<FriendlyPerson_tes> (  &<Person_tes> ;
          rdf:type [ <Person> ] ? ;
          <knows> @<Person> +
       ) ;
       rdf:type [ <FriendlyPerson> ]
    )
}

<Person>  (
    CLOSED {
       (  $<Person_tes> (  foaf:firstName @<String> * ;
             foaf:lastName @<String> ;
             foaf:age @<Int> ? ;
             <living> @<Boolean> ? ;
             foaf:knows @<Person> *
          ) ;
          rdf:type [ <Person> ]
       )
    } OR @<FriendlyPerson>
)



Person(id='42', last_name='smith', first_name=['Joe', 'Bob'], age=43, living=None, knows=[])
{
   "id": "42",
   "last_name": "smith",
   "first_name": [
      "Joe",
      "Bob"
   ],
   "age": 43,
   "living": null,
   "knows": [],
   "type": "Person",
   "@context": {
      "type": "@type",
      "ex": "http://example.org/model/",
      "foaf": "http://xmlns.com/foaf/0.1/",
      "xsd": "http://www.w3.org/2001/XMLSchema#",
      "@vocab": "http://example.org/model/",
      "age": {
         "@type": "xsd:integer",
         "@id": "foaf:age"
      },
      "first_name": {
         "@id": "foaf:firstName"
      },
      "id": "@id",
      "knows": {
         "@type": "@id",
         "@id": "foaf:knows"
      },
      "last_name": {
         "@id": "foaf:lastName"
      },
      "living": {
         "@type": "xsd:boolean"
      },
      "@base": "http://example.org/context/"
   }
}
@prefix : <http://example.org/model/> .
@prefix ex: <http://example.org/model/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<http://example.org/context/42> a ex:Person ;
    foaf:age 43 ;
    foaf:firstName "Bob",
        "Joe" ;
    foaf:lastName "smith" .


  Shape: http://example.org/sample/example1/Person not found in Schema
