Beispiel #1
0
def return_collection_or_concept_from_main_cache(uri):
    q = """
        PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

        SELECT DISTINCT *
        WHERE {{ 
            <{uri}> a ?c .
            OPTIONAL {{
                {{ <{uri}> skos:inScheme ?cs . }}
                UNION
                {{ <{uri}> skos:topConcpetOf ?cs . }}
                UNION
                {{ ?cs skos:member <{uri}> . }}
            }}           
        }}
        """.format(uri=uri)
    for r in u.sparql_query(q):
        if r["c"]["value"] in source.Source.VOC_TYPES:
            # if we find it and it's of a known class, return it
            # since, for a Concept or a Collection, we know the relevant vocab as vocab ==  CS ==  graph
            # in VocPrez's models of a vocabs
            vocab_uri = r["cs"]["value"]
            if r["c"][
                    "value"] == "http://www.w3.org/2004/02/skos/core#Collection":
                try:
                    c = getattr(source, g.VOCABS[vocab_uri].source) \
                        (vocab_uri, request, language=request.values.get("lang")).get_collection(uri)
                    return CollectionRenderer(request, c)
                except:
                    pass
            elif r["c"][
                    "value"] == "http://www.w3.org/2004/02/skos/core#Concept":
                try:
                    c = getattr(source, g.VOCABS[vocab_uri].source) \
                        (vocab_uri, request, language=request.values.get("lang")).get_concept(uri)
                    return ConceptRenderer(request, c)
                except:
                    pass
    return None
Beispiel #2
0
    def collect(details):
        """
        For this source, one SPARQL endpoint is given for a series of vocabs which are all separate ConceptSchemes

        'ga-jena-fuseki': {
            'source': VocabSource.SPARQL,
            'sparql_endpoint': 'http://dev2.nextgen.vocabs.ga.gov.au/fuseki/vocabs',
            'sparql_username': '******', # Optional username for SPARQL endpoint
            'sparql_password': '******', # Optional password for SPARQL endpoint
            #'uri_filter_regex': '.*', # Regular expression to filter vocabulary URIs - Everything
            #'uri_filter_regex': '^http(s?)://pid.geoscience.gov.au/def/voc/ga/', # Regular expression to filter vocabulary URIs - GA
            #'uri_filter_regex': '^https://gcmdservices.gsfc.nasa.gov', # Regular expression to filter vocabulary URIs - GCMD
            'uri_filter_regex': '^http(s?)://resource.geosciml.org/', # Regular expression to filter vocabulary URIs - CGI

        },
        """
        logging.debug("SPARQL collect()...")

        # Get all the ConceptSchemes from the SPARQL endpoint
        # Interpret each CS as a Vocab
        q = """
            PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
            PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
            PREFIX dcterms: <http://purl.org/dc/terms/>
            PREFIX owl: <http://www.w3.org/2002/07/owl#>
            SELECT * 
            WHERE {{
                ?cs a skos:ConceptScheme .
                OPTIONAL {{ ?cs skos:prefLabel ?title .
                    FILTER(lang(?title) = "{language}" || lang(?title) = "") }}
                OPTIONAL {{ ?cs dcterms:created ?created }}
                OPTIONAL {{ ?cs dcterms:issued ?issued }}
                OPTIONAL {{ ?cs dcterms:modified ?modified }}
                OPTIONAL {{ ?cs dcterms:creator ?creator }}
                OPTIONAL {{ ?cs dcterms:publisher ?publisher }}
                OPTIONAL {{ ?cs owl:versionInfo ?version }}
                OPTIONAL {{ ?cs skos:definition ?description .
                    FILTER(lang(?description) = "{language}" || lang(?description) = "") }}
            }} 
            ORDER BY ?title
            """.format(language=config.DEFAULT_LANGUAGE)
        # record just the IDs & title for the VocPrez in-memory vocabs list
        concept_schemes = u.sparql_query(
            q,
            details[
                "sparql_endpoint"],  # must specify a SPARQL endpoint if this source is to be a SPARQL source
            details.get("sparql_username"),
            details.get("sparql_password"),
        )
        assert concept_schemes is not None, "Unable to query for ConceptSchemes"

        sparql_vocabs = {}
        vocab_ids = []
        for cs in concept_schemes:
            vocab_id = cs["cs"]["value"]
            part = cs["cs"]["value"].split("#")[-1].split("/")[-1]
            if len(part) < 1:
                part = cs["cs"]["value"].split("#")[-1].split("/")[-2]
            id = part.lower()
            if id in vocab_ids:
                if id[-1].isnumeric():
                    id = id[:-1] + str(int(id[-1]) + 1)
                else:
                    id = id + "1"

            vocab_ids.append(id)

            sparql_vocabs[vocab_id] = Vocabulary(
                id,
                cs["cs"]["value"],
                cs["title"].get("value") or vocab_id if cs.get("title") else
                vocab_id,  # Need str for sorting, not None
                markdown(cs["description"].get("value"))
                if cs.get("description") is not None else None,
                cs["creator"].get("value")
                if cs.get("creator") is not None else None,
                dateutil.parser.parse(cs.get("created").get("value"))
                if cs.get("created") is not None else None,
                # dct:issued not in Vocabulary
                # dateutil.parser.parse(cs.get('issued').get('value')) if cs.get('issued') is not None else None,
                dateutil.parser.parse(cs.get("modified").get("value"))
                if cs.get("modified") is not None else None,
                cs["version"].get("value")
                if cs.get("version") is not None else None,  # versionInfo
                config.VocabSource.SPARQL,
                sparql_endpoint=details["sparql_endpoint"],
                sparql_username=details.get("sparql_username"),
                sparql_password=details.get("sparql_password"),
            )
        g.VOCABS = {**g.VOCABS, **sparql_vocabs}
        logging.debug("SPARQL collect() complete.")
Beispiel #3
0
    def get_collection(self, collection_uri):
        print("OGC get_collection()")
        # get the collection's metadata and members
        q = """
            PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
            PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

            SELECT DISTINCT *            
            WHERE {
                <xxxx> a skos:Collection ;
                       ?p ?o .

                FILTER(!isLiteral(?o) || lang(?o) = "en" || lang(?o) = "")

                OPTIONAL {
                    ?p skos:prefLabel|rdfs:label ?ppl .
                    FILTER(!isLiteral(?o) || lang(?o) = "en" || lang(?o) = "")
                }

                OPTIONAL {
                    ?o skos:prefLabel|rdfs:label ?opl .
                    FILTER(!isLiteral(?o) || lang(?o) = "en" || lang(?o) = "")
                }
            }
            """.replace("xxxx", collection_uri)

        vocab_uri = None
        pl = None
        d = None
        c = None
        s = {
            "provenance": None,
            "source": None,
            "wasDerivedFrom": None,
        }
        m = []
        found = False
        for r in u.sparql_query(q, config.SPARQL_ENDPOINT, config.SPARQL_USERNAME, config.SPARQL_PASSWORD):
            prop = r["p"]["value"]
            val = r["o"]["value"]
            found = True
            if val == "http://www.w3.org/2004/02/skos/core#Concept":
                return None

            if prop == "http://www.w3.org/2004/02/skos/core#prefLabel":
                pl = val
            elif prop == "http://www.w3.org/2004/02/skos/core#definition":
                d = val
            elif prop == "http://www.w3.org/2000/01/rdf-schema#comment":
                c = val
            elif prop == "http://purl.org/dc/terms/provenance":
                s["provenance"] = val
            elif prop == "http://purl.org/dc/terms/source":
                s["source"] = val
            elif prop == "http://www.w3.org/2004/02/skos/core#inScheme":
                s["inScheme"] = val
                vocab_uri = val
            elif prop == "http://www.w3.org/ns/prov#wasDerivedFrom":
                s["wasDerivedFrom"] = val
            elif prop == "http://www.w3.org/2004/02/skos/core#member":
                m.append(Property(prop, "Member", val, r["opl"]["value"]))

        if not found:
            return None

        from vocprez.model.collection import Collection
        if not d:
            d = c
        return Collection(vocab_uri, collection_uri, pl, d, s, sorted(m, key=lambda x: x.value_label.lower()))
Beispiel #4
0
def search():
    if request.values.get("search"):
        last_search = request.values.get("search")
        if request.values.get("from") and request.values.get("from") != "all":
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

                SELECT DISTINCT ?uri ?pl (SUM(?weight) AS ?weight)
                WHERE {{
                    GRAPH <{grf}> {{
                        {{  # exact match on a prefLabel always wins
                            ?uri a skos:Concept ;
                                 skos:prefLabel ?pl .
                            BIND (50 AS ?weight)
                            FILTER REGEX(?pl, "^{input}$", "i")
                        }}
                        UNION    
                        {{
                            ?uri a skos:Concept ;
                                 skos:prefLabel ?pl .
                            BIND (10 AS ?weight)
                            FILTER REGEX(?pl, "{input}", "i")
                        }}
                        UNION
                        {{
                            ?uri a skos:Concept ;
                                 skos:altLabel ?al ;
                                 skos:prefLabel ?pl .
                            BIND (5 AS ?weight)
                            FILTER REGEX(?al, "{input}", "i")
                        }}
                        UNION
                        {{
                            ?uri a skos:Concept ;
                                 skos:hiddenLabel ?hl ;
                                 skos:prefLabel ?pl .
                            BIND (5 AS ?weight)
                            FILTER REGEX(?hl, "{input}", "i")
                        }}        
                        UNION
                        {{
                            ?uri a skos:Concept ;
                                 skos:definition ?d ;
                                 skos:prefLabel ?pl .
                            BIND (1 AS ?weight)
                            FILTER REGEX(?d, "{input}", "i")
                        }}        
                    }}
                }}
                GROUP BY ?uri ?pl
                ORDER BY DESC(?weight) 
                """.format(
                **{
                    "grf": request.values.get("from"),
                    "input": request.values.get("search")
                })
            results = []
        else:
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
                SELECT DISTINCT ?g ?uri ?pl (SUM(?weight) AS ?weight)
                WHERE {{
                    GRAPH ?g {{
                        {{  # exact match on a prefLabel always wins
                            ?uri a skos:Concept ;
                                 skos:prefLabel ?pl .
                            BIND (50 AS ?weight)
                            FILTER REGEX(?pl, "^{input}$", "i")
                        }}
                        UNION    
                        {{
                            ?uri a skos:Concept ;
                                 skos:prefLabel ?pl .
                            BIND (10 AS ?weight)
                            FILTER REGEX(?pl, "{input}", "i")
                        }}
                        UNION
                        {{
                            ?uri a skos:Concept ;
                                 skos:altLabel ?al ;
                                 skos:prefLabel ?pl .
                            BIND (5 AS ?weight)
                            FILTER REGEX(?al, "{input}", "i")
                        }}
                        UNION
                        {{
                            ?uri a skos:Concept ;
                                 skos:hiddenLabel ?hl ;
                                 skos:prefLabel ?pl .
                            BIND (5 AS ?weight)
                            FILTER REGEX(?hl, "{input}", "i")
                        }}        
                        UNION
                        {{
                            ?uri a skos:Concept ;
                                 skos:definition ?d ;
                                 skos:prefLabel ?pl .
                            BIND (1 AS ?weight)
                            FILTER REGEX(?d, "{input}", "i")
                        }}        
                    }}
                }}
                GROUP BY ?g ?uri ?pl
                ORDER BY DESC(?weight) 
                """.format(**{"input": request.values.get("search")})
            results = {}

        for r in u.sparql_query(q):
            if r.get("uri") is None:
                break  # must do this check as r["weight"] will appear at least once with value 0 for no results
            if request.values.get(
                    "from") and request.values.get("from") != "all":
                results.append((r["uri"]["value"], r["pl"]["value"]))
            else:
                if r["g"]["value"] not in results.keys():
                    results[r["g"]["value"]] = []
                results[r["g"]["value"]].append(
                    (r["uri"]["value"], r["pl"]["value"]))

        return render_template("search.html",
                               vocabs=[(v.uri, v.title)
                                       for k, v in g.VOCABS.items()],
                               last_search=last_search,
                               selected_vocab=request.values.get("from"),
                               results=results)
    else:
        return render_template("search.html",
                               vocabs=[(v.uri, v.title)
                                       for k, v in g.VOCABS.items()])
Beispiel #5
0
def object():
    """
    This is the general RESTful endpoint and corresponding Python function to handle requests for individual objects,
    be they a Vocabulary (ConceptScheme), a Collection or Concept. Only those 3 classes of object are supported for the
    moment.

    An HTTP URI query string argument parameter 'uri' must be supplied, indicating the URI of the object being requested

    :return: A Flask Response object
    :rtype: :class:`flask.Response`
    """

    uri = request.values.get("uri")

    # must have a URI or Vocab URI supplied
    if uri is None:
        return return_vocprez_error(
            "Input Error", 400,
            "A Query String Argument of 'uri' must be supplied for this endpoint"
        )

    if uri == config.SYSTEM_BASE_URI or uri == config.SYSTEM_BASE_URI + "/":
        return index()

    if uri == config.VOCS_URI or uri == config.VOCS_URI + "/":
        return vocabularies()

    # get the class of the object
    q = """
        PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

        SELECT DISTINCT ?c ?cs
        WHERE {
            GRAPH ?g {
                <xxx> a ?c .
                OPTIONAL {
                    VALUES ?memberof { skos:inScheme skos:topConceptOf }
                    <xxx> ?memberof ?cs .
                }
            }
        }
        """.replace("xxx", uri)
    cs = None
    for r in u.sparql_query(q):
        if r["c"][
                "value"] == "http://www.w3.org/2004/02/skos/core#ConceptScheme":
            if uri in g.VOCABS.keys():
                # get vocab details using appropriate source handler
                vocab = source.SPARQL(request).get_vocabulary(uri)
                return VocabularyRenderer(request, vocab).render()
            else:
                return None
        elif r["c"][
                "value"] == "http://www.w3.org/2004/02/skos/core#Collection":
            try:
                c = source.SPARQL(request).get_collection(uri)
                return CollectionRenderer(request, c).render()
            except:
                return None
        elif r["c"]["value"] == "http://www.w3.org/2004/02/skos/core#Concept":
            try:
                if r.get("cs"):
                    cs = r["cs"]["value"]
                c = source.SPARQL(request).get_concept(cs, uri)
                return ConceptRenderer(request, c).render()
            except:
                return None

    return return_vocprez_error(
        "Input Error", 400,
        "The object with URI {} is not of type skos:ConceptScheme, skos:Collection or skos:Concept "
        "and only these classes of object are understood by VocPrez".format(
            uri))
Beispiel #6
0
    def get_concept(self, uri):
        vocab = g.VOCABS[self.vocab_uri]
        q = """
            PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
            PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

            SELECT DISTINCT *            
            WHERE {{
                <{concept_uri}> a skos:Concept ;
                                ?p ?o .

                OPTIONAL {{
                    ?o skos:prefLabel ?ropl .
                }}                
            }}
            """.format(concept_uri=uri)

        pl = None
        d = None
        s = {
            "provenance": None,
            "source": None,
            "wasDerivedFrom": None,
        }
        annotation_types = {
            "http://www.opengis.net/def/metamodel/ogc-na/status": "Status",
            'http://www.w3.org/2004/02/skos/core#altLabel':
            "Alternative Label",
            'http://www.w3.org/2004/02/skos/core#note': "Note",
            'http://www.w3.org/2004/02/skos/core#scopeNote': "Scope Note",
            'http://www.w3.org/2004/02/skos/core#hostryNote': "History Note",
        }
        annotations = []
        agent_types = {
            'http://purl.org/dc/terms/contributor': "Contributor",
            'http://purl.org/dc/terms/creator': "Creator",
            'http://purl.org/dc/terms/publisher': "Publisher",
        }
        agent = {}
        related_instance_types = {
            'http://www.w3.org/2004/02/skos/core#exactMatch': "Exact Match",
            'http://www.w3.org/2004/02/skos/core#closeMatch': "Close Match",
            'http://www.w3.org/2004/02/skos/core#broadMatch': "Broad Match",
            'http://www.w3.org/2004/02/skos/core#narrowMatch': "Narrow Match",
            'http://www.w3.org/2004/02/skos/core#broader': "Broader",
            'http://www.w3.org/2004/02/skos/core#narrower': "Narrower"
        }
        provenance_property_types = {
            "http://purl.org/pav/hasCurrentVersion": "Has Current Version",
            "http://purl.org/pav/version": "Version",
            "http://www.w3.org/2002/07/owl#deprecated": "Deprecated",
            "http://purl.org/pav/previousVersion": "Previous Version",
            "http://purl.org/dc/terms/isVersionOf": "Is Version Of",
            "http://purl.org/pav/authoredOn": "Authored On"
        }
        related_instances = {}

        other_properties = []
        for r in u.sparql_query(q, vocab.sparql_endpoint,
                                vocab.sparql_username, vocab.sparql_password):
            if r["p"][
                    "value"] == "http://www.w3.org/2004/02/skos/core#prefLabel":
                pl = r["o"]["value"]
            elif r["p"][
                    "value"] == "http://www.w3.org/2004/02/skos/core#definition":
                d = r["o"]["value"]
            elif r["p"]["value"] == "http://purl.org/dc/terms/provenance":
                s["provenance"] = r["o"]["value"]
            elif r["p"]["value"] == "http://purl.org/dc/terms/source":
                s["source"] = r["o"]["value"]
            elif r["p"]["value"] == "http://www.w3.org/ns/prov#wasDerivedFrom":
                s["wasDerivedFrom"] = r["o"]["value"]

            elif r["p"]["value"] in annotation_types.keys():
                annotations.append(
                    Property(r["p"]["value"],
                             annotation_types[r["p"]["value"]],
                             r["o"]["value"]))

            elif r["p"]["value"] in related_instance_types.keys():
                if related_instances.get(r["p"]["value"]) is None:
                    related_instances[r["p"]["value"]] = {}
                    related_instances[r["p"]["value"]] = {
                        "instances": [],
                        "label": related_instance_types[r["p"]["value"]]
                    }
                related_instances[r["p"]["value"]]["instances"].append(
                    (r["o"]["value"], r["ropl"]["value"]
                     if r.get("ropl") is not None else None))

            elif r["p"]["value"] in provenance_property_types.keys():
                other_properties.append(
                    Property(r["p"]["value"],
                             provenance_property_types[r["p"]["value"]],
                             r["o"]["value"].rstrip(".0")))

            elif r["p"][
                    "value"] == "http://www.w3.org/2004/02/skos/core#altLabel":
                other_properties.append(
                    Property(r["p"]["value"], "Alternative Label",
                             r["o"]["value"]))

            # TODO: Agents

            # TODO: more Annotations

        if pl is None:
            return None

        from vocprez.model.concept import Concept

        return Concept(self.vocab_uri,
                       uri,
                       pl,
                       d,
                       related_instances,
                       annotations=annotations,
                       other_properties=other_properties)
Beispiel #7
0
    def list_concepts_for_a_collection(self, acc_dep=None):
        vocab = g.VOCABS[self.vocab_uri]

        if acc_dep == "accepted":
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

                SELECT DISTINCT ?c ?pl ?dep
                WHERE {{
                        <{vocab_uri}> skos:member ?c .
                        
                        ?c <http://www.w3.org/2002/07/owl#deprecated> "false" .

                        OPTIONAL {{
                            ?c <http://www.w3.org/2002/07/owl#deprecated> ?dep .
                        }}

                        ?c skos:prefLabel ?pl .
                        FILTER(lang(?pl) = "{language}" || lang(?pl) = "") 
                }}
                ORDER BY ?pl
                """.format(vocab_uri=vocab.uri, language=self.language)
        elif acc_dep == "deprecated":
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

                SELECT DISTINCT ?c ?pl ?dep
                WHERE {{
                        <{vocab_uri}> skos:member ?c .
                        
                        ?c <http://www.w3.org/2002/07/owl#deprecated> "true" .

                        OPTIONAL {{
                            ?c <http://www.w3.org/2002/07/owl#deprecated> ?dep .
                        }}

                        ?c skos:prefLabel ?pl .
                        FILTER(lang(?pl) = "{language}" || lang(?pl) = "") 
                }}
                ORDER BY ?pl
                """.format(vocab_uri=vocab.uri, language=self.language)
        else:
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

                SELECT DISTINCT ?c ?pl ?dep
                WHERE {{
                        <{vocab_uri}> skos:member ?c .

                        OPTIONAL {{
                            ?c <http://www.w3.org/2002/07/owl#deprecated> ?dep .
                        }}

                        ?c skos:prefLabel ?pl .
                        FILTER(lang(?pl) = "{language}" || lang(?pl) = "") 
                }}
                ORDER BY ?pl
                """.format(vocab_uri=vocab.uri, language=self.language)

        return [(concept["c"]["value"], concept["pl"]["value"],
                 True if concept.get("dep")
                 and concept["dep"]["value"] == "true" else False)
                for concept in
                u.sparql_query(q, vocab.sparql_endpoint, vocab.sparql_username,
                               vocab.sparql_password)]
Beispiel #8
0
    def list_concepts(self, acc_dep=None):
        vocab = g.VOCABS[self.vocab_uri]

        if acc_dep == "accepted":
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
                SELECT DISTINCT ?c ?pl ?broader ?dep
                WHERE {{
                    {{?c skos:inScheme <{vocab_uri}>}}

                    ?c a skos:Concept ;
                         skos:prefLabel ?pl .
                        
                    ?c <http://www.w3.org/2002/07/owl#deprecated> "false" .

                    OPTIONAL {{
                        {{?c skos:broader ?broader}}
                        UNION 
                        {{?broader skos:narrower ?c}}
                    }}

                    FILTER(lang(?pl) = "{language}" || lang(?pl) = "") 
                }}
                ORDER BY ?pl
                """.format(vocab_uri=vocab.uri, language=self.language)
        elif acc_dep == "deprecated":
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
                SELECT DISTINCT ?c ?pl ?broader ?dep
                WHERE {{
                    {{?c skos:inScheme <{vocab_uri}>}}

                    ?c a skos:Concept ;
                         skos:prefLabel ?pl .
                         
                    ?c <http://www.w3.org/2002/07/owl#deprecated> "true" .

                    OPTIONAL {{
                        {{?c skos:broader ?broader}}
                        UNION 
                        {{?broader skos:narrower ?c}}
                    }}

                    FILTER(lang(?pl) = "{language}" || lang(?pl) = "") 
                }}
                ORDER BY ?pl
                """.format(vocab_uri=vocab.uri, language=self.language)
        else:
            q = """
                PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
                SELECT DISTINCT ?c ?pl ?broader ?dep
                WHERE {{
                    {{?c skos:inScheme <{vocab_uri}>}}

                    ?c a skos:Concept ;
                         skos:prefLabel ?pl .

                    OPTIONAL {{
                        {{?c skos:broader ?broader}}
                        UNION 
                        {{?broader skos:narrower ?c}}
                    }}

                    FILTER(lang(?pl) = "{language}" || lang(?pl) = "") 
                }}
                ORDER BY ?pl
                """.format(vocab_uri=vocab.uri, language=self.language)

        return [
            (concept["c"]["value"], concept["pl"]["value"],
             concept["broader"]["value"] if concept.get("broader") else None)
            for concept in u.sparql_query(q, vocab.sparql_endpoint,
                                          vocab.sparql_username,
                                          vocab.sparql_password)
        ]
Beispiel #9
0
    def collect(details):
        """
        For this source, one SPARQL endpoint is given for a series of vocabs which are all separate ConceptSchemes

        'ga-jena-fuseki': {
            'source': VocabSource.SPARQL,
            'sparql_endpoint': 'http://dev2.nextgen.vocabs.ga.gov.au/fuseki/vocabs',
            'sparql_username': '******', # Optional username for SPARQL endpoint
            'sparql_password': '******', # Optional password for SPARQL endpoint
            #'uri_filter_regex': '.*', # Regular expression to filter vocabulary URIs - Everything
            #'uri_filter_regex': '^http(s?)://pid.geoscience.gov.au/def/voc/ga/', # Regular expression to filter vocabulary URIs - GA
            #'uri_filter_regex': '^https://gcmdservices.gsfc.nasa.gov', # Regular expression to filter vocabulary URIs - GCMD
            'uri_filter_regex': '^http(s?)://resource.geosciml.org/', # Regular expression to filter vocabulary URIs - CGI

        },
        """
        logging.debug("SPARQL collect()...")

        # Get all the ConceptSchemes from the SPARQL endpoint
        # Interpret each CS as a Vocab
        q = """
            PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
            PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
            PREFIX dcterms: <http://purl.org/dc/terms/>
            PREFIX owl: <http://www.w3.org/2002/07/owl#>
            SELECT * WHERE {{
                {{?cs a skos:ConceptScheme .}}
                UNION
                {{?cs a skos:Collection .}}
                ?cs a ?t .
                OPTIONAL {{ ?cs skos:prefLabel ?title .
                    FILTER(lang(?title) = "{language}" || lang(?title) = "") }}
                OPTIONAL {{ ?cs dcterms:created ?created }}
                OPTIONAL {{ ?cs dcterms:issued ?issued }}
                OPTIONAL {{ ?cs dcterms:date ?modified }}
                OPTIONAL {{ ?cs dcterms:modified ?modified }}
                OPTIONAL {{ ?cs dcterms:creator ?creator }}
                OPTIONAL {{ ?cs dcterms:publisher ?publisher }}
                OPTIONAL {{ ?cs owl:versionInfo ?version }}
                OPTIONAL {{ ?cs dcterms:description ?description .
                    FILTER(lang(?description) = "{language}" || lang(?description) = "") }}   
                # NVS special properties                 
                OPTIONAL {{
                    ?cs <http://www.isotc211.org/schemas/grg/RE_RegisterManager> ?registermanager .
                    ?cs <http://www.isotc211.org/schemas/grg/RE_RegisterOwner> ?registerowner .
                }}                
                OPTIONAL {{ ?cs rdfs:seeAlso ?seeAlso }}                
            }} 
            ORDER BY ?title
            """.format(language=config.DEFAULT_LANGUAGE)
        # record just the IDs & title for the VocPrez in-memory vocabs list
        concept_schemes = u.sparql_query(
            q,
            details[
                "sparql_endpoint"],  # must specify a SPARQL endpoint if this source is to be a SPARQL source
            details.get("sparql_username"),
            details.get("sparql_password"),
        )
        assert concept_schemes is not None, "Unable to query for ConceptSchemes"

        sparql_vocabs = {}
        for cs in concept_schemes:
            vocab_id = cs["cs"]["value"]

            other_properties = []
            other_properties.append(
                Property(
                    "http://purl.org/dc/terms/identifier", "Identifier",
                    Literal(cs["cs"]["value"].replace(
                        "http://vocab.nerc.ac.uk/collection/",
                        "").replace("http://vocab.nerc.ac.uk/scheme/",
                                    "").replace("/current/", ""))))
            if cs.get("registermanager") is not None:
                other_properties.append(
                    Property(
                        "http://www.isotc211.org/schemas/grg/RE_RegisterManager",
                        "Register Manager",
                        Literal(cs["registermanager"]["value"])))
            if cs.get("registerowner") is not None:
                other_properties.append(
                    Property(
                        "http://www.isotc211.org/schemas/grg/RE_RegisterOwner",
                        "Register Owner",
                        Literal(cs["registerowner"]["value"])))
            if cs.get("seeAlso") is not None:
                other_properties.append(
                    Property("http://www.w3.org/2000/01/rdf-schema#seeAlso",
                             "See Also", URIRef(cs["seeAlso"]["value"])))

            sparql_vocabs[vocab_id] = Vocabulary(
                cs["cs"]["value"],
                cs["cs"]["value"],
                cs["title"].get("value") or vocab_id if cs.get("title") else
                vocab_id,  # Need str for sorting, not None
                cs["description"].get("value")
                if cs.get("description") is not None else None,
                cs["creator"].get("value")
                if cs.get("creator") is not None else None,
                dateutil.parser.parse(cs.get("created").get("value"))
                if cs.get("created") is not None else None,
                # dct:issued not in Vocabulary
                # dateutil.parser.parse(cs.get('issued').get('value')) if cs.get('issued') is not None else None,
                dateutil.parser.parse(cs.get("modified").get("value"))
                if cs.get("modified") is not None else None,
                cs["version"].get("value")
                if cs.get("version") is not None else None,  # versionInfo
                config.VocabSource.
                NvsSPARQL,  # TODO: replace this var with a reference to self class type (Source type)
                collections=str(cs["t"]["value"]).split("#")[-1],
                sparql_endpoint=details["sparql_endpoint"],
                sparql_username=details.get("sparql_username"),
                sparql_password=details.get("sparql_password"),
                other_properties=other_properties)
        logging.debug("pickle latest standard_name")
        import requests
        from pathlib import Path
        import pickle

        r = requests.get("http://vocab.nerc.ac.uk/standard_name/")
        gr = Graph()
        gr.parse(data=r.text, format="xml")
        with open(Path(config.APP_DIR) / "cache" / "standard_name.p",
                  "wb") as f:
            pickle.dump(gr, f)

        for cs in gr.query(q):
            vocab_id = str(cs["cs"])

            other_properties = []
            other_properties.append(
                Property("http://purl.org/dc/terms/identifier", "Identifier",
                         Literal("standard_name")))
            # the following properties are filled with blanks, not None, in the vocab
            # if cs.get("registermanager") is not None:
            #     other_properties.append(
            #         Property(
            #             "http://www.isotc211.org/schemas/grg/RE_RegisterManager",
            #             "Register Manager",
            #             Literal(cs["registermanager"])
            #         )
            #     )
            # if cs.get("registerowner") is not None:
            #     other_properties.append(
            #         Property(
            #             "http://www.isotc211.org/schemas/grg/RE_RegisterOwner",
            #             "Register Owner",
            #             Literal(cs["registerowner"])
            #         )
            #     )
            # if cs.get("seeAlso") is not None:
            #     other_properties.append(
            #         Property(
            #             "http://www.w3.org/2000/01/rdf-schema#seeAlso",
            #             "See Also",
            #             URIRef(cs["seeAlso"])
            #         )
            #     )

            sparql_vocabs[vocab_id] = Vocabulary(
                "standard_name",
                vocab_id,
                str(cs["title"]),
                str(cs["description"]),
                str(cs["creator"]),
                None,
                # dct:issued not in Vocabulary
                # dateutil.parser.parse(cs.get('issued').get('value')) if cs.get('issued') is not None else None,
                dateutil.parser.parse(cs.get("modified")),
                str(cs["version"]),  # versionInfo
                config.VocabSource.NvsSPARQL,
                collections="Collection",  # just like the other Collections
                sparql_endpoint=details["sparql_endpoint"],
                sparql_username=details.get("sparql_username"),
                sparql_password=details.get("sparql_password"),
                other_properties=other_properties)

        g.VOCABS = {}
        g.VOCABS.update(**sparql_vocabs)
        logging.debug("NvsSPARQL collect() complete.")