@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix lkg: <http://lkg.lynx-project.eu/def/> .
@prefix eli:   <http://data.europa.eu/eli/ontology#> .
@prefix dct:   <http://purl.org/dc/terms/> .
@prefix itsrdf: <http://www.w3.org/2005/11/its/rdf#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix nif:   <http://persistence.uni-leipzig.org/nlp2rdf/ontologies/nif-core#> .
@prefix swc: <http://semantic-web.com/shapes/> .

lkg:LynxDocumentShape
    a sh:NodeShape ;
    sh:targetClass lkg:LynxDocument ;
    sh:closed false ;
    sh:property [
                    sh:path eli:hasPart ;
                    sh:node lkg:LynxDocumentPartShape ;
                ],
                [
                    sh:path itsrdf:target ;
                    sh:datatype rdf:langString ;
                    sh:uniqueLang true ;
                ],
                [
                    sh:path nif:isString ;
                    sh:description "A valid LynxDocument should only use the nif:isString property to define the text of the context. nif:contextStringRef is not supported.";
                    sh:minCount 1 ;
                    sh:maxCount 1 ;
                    sh:datatype xsd:string ;
                ],
                [
                    sh:path rdf:type ;
                    sh:hasValue nif:Context ;
                ],
                [
                    sh:path lkg:metadata ;
                    sh:minCount 1 ;
                    sh:maxCount 1 ;
                    sh:class lkg:Metadata ;
                    sh:node lkg:MetadataShape ;
                ] .

lkg:LynxDocumentPartShape
    a sh:NodeShape ;
    sh:targetClass lkg:LynxDocumentPart ;
    sh:property [
                    sh:path lkg:parent ;
                    sh:maxCount 1 ;
                    sh:class lkg:LynxDocumentPart ;
                    sh:nodeKind sh:IRI ;
                ],
                [
                    sh:path dct:title;
                    sh:datatype rdf:langString ;
                    sh:uniqueLang true ;
                ],
                [
                    sh:path rdf:type ;
                    sh:hasValue nif:OffsetBasedString ;
                ] .

lkg:MetadataShape
    a sh:NodeShape ;
    sh:targetClass lkg:Metadata ;
    sh:property [
                    sh:path dct:language;
                    sh:minCount 1;
                    sh:maxCount 1;
                    sh:in ( "aa" "ab" "ae" "af" "ak" "am" "an" "as" "av" "ay" "az" "ba" "be" "bg" "bh" "bi" "bm" "bn" "bo" "br" "bs" "ca" "ce" "ch" "co" "cr" "cs" "cu" "cv" "cy" "da" "de" "dv" "dz" "ee" "el" "en" "eo" "es" "et" "eu" "fa" "ff" "fi" "fj" "fo" "fr" "fy" "ga" "gd" "gl" "gn" "gu" "gv" "ha" "he" "hi" "ho" "hr" "ht" "hu" "hy" "hz" "ia" "id" "ie" "ig" "ii" "ik" "io" "is" "it" "iu" "ja" "jv" "ka" "kg" "ki" "kj" "kk" "kl" "km" "kn" "ko" "kr" "ks" "ku" "kv" "kw" "ky" "la" "lb" "lg" "li" "ln" "lo" "lt" "lu" "lv" "mg" "mh" "mi" "mk" "ml" "mn" "mr" "ms" "mt" "my" "na" "nb" "nd" "ne" "ng" "nl" "nn" "no" "nr" "nv" "ny" "oc" "oj" "om" "or" "os" "pa" "pi" "pl" "ps" "pt" "qu" "rm" "rn" "ro" "ru" "rw" "sa" "sc" "sd" "se" "sg" "si" "sk" "sl" "sm" "sn" "so" "sq" "sr" "ss" "st" "su" "sv" "sw" "ta" "te" "tg" "th" "ti" "tk" "tl" "tn" "to" "tr" "ts" "tt" "tw" "ty" "ug" "uk" "ur" "uz" "ve" "vi" "vo" "wa" "wo" "xh" "yi" "yo" "za" "zh" "zu" ) ;
                ],
                [
                    sh:path dct:title;
                    sh:datatype rdf:langString ;
                    sh:uniqueLang true ;
                ],
                [
                    sh:path lkg:summary;
                    sh:datatype rdf:langString ;
                    sh:uniqueLang true ;
                ],
                [
                    sh:path dct:subject;
                    sh:datatype rdf:langString ;
                ],
                [
                    sh:path eli:version_date ;
                    sh:datatype xsd:date ;
                    sh:maxCount 1;
                    #TODO: define some pattern to be used as validation, format should be valid according to http://books.xmlschemata.org/relaxng/ch19-77041.html
                ],
                [
                    sh:path dct:created ;
                    sh:datatype xsd:dateTime ;
                    sh:maxCount 1;
                    #TODO: define some pattern to be used as validation, format should be valid according to http://books.xmlschemata.org/relaxng/ch19-77049.html
                ],
                [
                    sh:path eli:id_local;
                    sh:minCount 1;
                    sh:maxCount 1;
                    sh:datatype xsd:string ;
                ],
                [
                    sh:path lkg:wasExtractedFrom;
                    sh:datatype xsd:string ;
                    sh:maxCount 1;
                    swc:pattern swc:UriPattern ;
                ],
                [
                    sh:message "006 - There can be at most one jurisdiction";
                    sh:path eli:jurisdiction;
                    sh:maxCount 1;
                    sh:datatype xsd:string ;
                    sh:in ("AF" "AX" "AL" "DZ" "AS" "AD" "AO" "AI" "AQ" "AG" "AR" "AM" "AW" "AU" "AT" "AZ" "BS" "BH" "BD" "BB" "BY" "BE" "BZ" "BJ" "BM" "BT" "BO" "BQ" "BA" "BW" "BV" "BR" "IO" "BN" "BG" "BF" "BI" "KH" "CM" "CA" "CV" "KY" "CF" "TD" "CL" "CN" "CX" "CC" "CO" "KM" "CG" "CD" "CK" "CR" "CI" "HR" "CU" "CW" "CY" "CZ" "DK" "DJ" "DM" "DO" "EC" "EG" "SV" "GQ" "ER" "EE" "ET" "FK" "FO" "FJ" "FI" "FR" "GF" "PF" "TF" "GA" "GM" "GE" "DE" "GH" "GI" "GR" "GL" "GD" "GP" "GU" "GT" "GG" "GN" "GW" "GY" "HT" "HM" "VA" "HN" "HK" "HU" "IS" "IN" "ID" "IR" "IQ" "IE" "IM" "IL" "IT" "JM" "JP" "JE" "JO" "KZ" "KE" "KI" "KP" "KR" "KW" "KG" "LA" "LV" "LB" "LS" "LR" "LY" "LI" "LT" "LU" "MO" "MK" "MG" "MW" "MY" "MV" "ML" "MT" "MH" "MQ" "MR" "MU" "YT" "MX" "FM" "MD" "MC" "MN" "ME" "MS" "MA" "MZ" "MM" "NA" "NR" "NP" "NL" "NC" "NZ" "NI" "NE" "NG" "NU" "NF" "MP" "NO" "OM" "PK" "PW" "PS" "PA" "PG" "PY" "PE" "PH" "PN" "PL" "PT" "PR" "QA" "RE" "RO" "RU" "RW" "BL" "SH" "KN" "LC" "MF" "PM" "VC" "WS" "SM" "ST" "SA" "SN" "RS" "SC" "SL" "SG" "SX" "SK" "SI" "SB" "SO" "ZA" "GS" "SS" "ES" "LK" "SD" "SR" "SJ" "SZ" "SE" "CH" "SY" "TW" "TJ" "TZ" "TH" "TL" "TG" "TK" "TO" "TT" "TN" "TR" "TM" "TC" "TV" "UG" "UA" "AE" "GB" "US" "UM" "UY" "UZ" "VU" "VE" "VN" "VG" "VI" "WF" "EH" "YE" "ZM" "ZW") ;
                ],
                [
                    sh:path owl:sameAs ;
                    sh:nodeKind sh:IRI ;
                ],
                [
                    sh:path lkg:hasEli ;
                    sh:maxCount 1 ;
                    sh:nodeKind sh:IRI ;
                ],
                [
                    sh:path lkg:hasDbpedia ;
                    sh:maxCount 1 ;
                    sh:nodeKind sh:IRI ;
                ],
                [
                    sh:path lkg:hasPDF ;
                    sh:maxCount 1 ;
                    sh:datatype xsd:string ;
                    swc:pattern swc:UriPattern ;
                ],
                [
                    sh:path lkg:hasWikipedia ;
                    sh:maxCount 1 ;
                    sh:datatype xsd:string ;
                    swc:pattern swc:UriPattern ;
                ].

##TODO: to refactor
lkg:LegislationShape
    a sh:NodeShape ;
    sh:targetClass lkg:Legislation ;
    sh:and ( lkg:LynxDocumentShape ) ;
    sh:property [
                    sh:path lkg:metadata ;
                    sh:property [
                                    sh:path eli:jurisdiction;
                                    sh:minCount 1;
                                ];
                ] .

swc:PatternConstraintComponentUsingASK
    a sh:ConstraintComponent ;
    rdfs:label "URI pattern constraint component" ;
    sh:parameter [
                     sh:path swc:pattern ;
                     sh:name "Pattern Node" ;
                     sh:description "The pattern node." ;
                 ] ;
    sh:labelTemplate "Values are literals matching the pattern specified by {$pattern}" ;
    sh:validator swc:hasPattern .

swc:hasPattern
    a sh:SPARQLAskValidator ;
    sh:message "Values are literals matching the pattern specified by {$pattern}" ;
    sh:ask """
        ASK
            {
                FILTER (!isBlank($value) && IF(bound(?flags), regex(str($value), ?pattern2, ?flags), regex(str($value), ?pattern2)))
                GRAPH $shapesGraph {
                    $pattern sh:pattern ?pattern2  .
                    OPTIONAL { $pattern sh:flags   ?flags } .
                }
            }
        """ ;
    sh:prefixes <http://www.w3.org/ns/shacl#> ;
.

swc:UriPattern sh:pattern """^(?:(?:[A-Za-z][+-.\\w^_]*:/{2})?(?:\\S+(?::\\S*)?@)?(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/\\S*)?)$""" ;
               sh:flags "i" .

## TODO: implement pattern for URL checking