<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context  
                        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="schema_org_description" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="abstract" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
                PREFIX SO:   <http://schema.org/>

                SELECT (str(?member) as ?abstract)
                WHERE {
                    ?datasetId rdf:type SO:Dataset .
                    ?datasetId SO:description ?list .
                    ?list list:index (?pos ?member) .
                    # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                    FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                }
                order by (?pos)
                limit 1


                ]]>
            </value>
        </constructor-arg>
    </bean>
    
    <bean id="schema_org_name" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="title" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                PREFIX SO:   <http://schema.org/>
                SELECT ( ?name as ?title )
                WHERE {
                    ?datasetId rdf:type SO:Dataset .
                    ?datasetId SO:name ?name .
                    # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                    FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                }
                limit 1
                 ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_alternateName" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="label" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                PREFIX SO:   <http://schema.org/>

                SELECT ?label
                WHERE {
                    ?datasetId rdf:type SO:Dataset .
                    ?datasetId SO:alternateName ?label .
                    # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                    FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                }
                limit 1
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_award_id" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="awardNumber" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        ( str(?identifier) as ?awardNumber)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        {
                            ?awardId rdf:type SO:MonetaryGrant .
                            ?awardId SO:fundedItem ?datasetId .
                            ?awardId SO:identifier ?identifier .
                        }
                        UNION
                        {
                            ?datasetId SO:about ?awardId .
                            ?awardId rdf:type SO:MonetaryGrant .
                            ?awardId SO:sameAs ?identifier .
                        }
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_award_name" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="awardTitle" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        ( str(?name) as ?awardTitle)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        {
                            ?awardId rdf:type SO:MonetaryGrant .
                            ?awardId SO:fundedItem ?datasetId .
                            ?awardId SO:name ?name .
                        }
                        UNION
                        {
                            ?datasetId SO:about ?awardId .
                            ?awardId rdf:type SO:MonetaryGrant .
                            ?awardId SO:name ?name .
                        }
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <!-- Extract one SO:creator to populate Solr 'author'. The convention used is to extract
         the first creator in document order and use that. The JSON-LD list must be ordered
         by using '@list', so that an ordered list is created when converted to an RDF model.
         Also, in order to process the list efficiently in SPARQL, the Jena ARQ 'list' facility
         is used for the query, vs a native SPARQL query, which would take significantly longer.
    -->
    <bean id="schema_org_creator" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="author" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
                PREFIX SO:   <http://schema.org/>

                SELECT (?name as ?author)
                WHERE {
                    ?dsId rdf:type SO:Dataset .
                    ?dsId SO:creator ?list .
                    ?list list:index (?pos ?member) .
                    ?member SO:name ?name .
                }
                order by (?pos)
                limit 1
                ]]>
            </value>
        </constructor-arg>
    </bean>



    <bean id="schema_org_datePublished" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="pubDate" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        ( str(?datePublished) as ?pubDate)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId SO:datePublished ?datePublished
                        # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                        FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                    }
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="dateConverter" />
    </bean>

    <bean id="schema_org_givenName" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="authorGivenName" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
                PREFIX SO:   <http://schema.org/>

                SELECT (?givenName as ?authorGivenName)
                WHERE {
                    ?dsId rdf:type SO:Dataset .
                    ?dsId SO:creator ?list .
                    ?list list:index (?pos ?member) .
                    ?member SO:givenName ?givenName .
                }
                order by (?pos)
                limit 1
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_familyName" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="authorLastName" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
                    PREFIX SO:  <http://schema.org/>

                    SELECT (?familyName as ?authorLastName)
                    WHERE {
                        ?dsId rdf:type SO:Dataset .
                        ?dsId SO:creator ?list .
                        ?list list:index (?pos ?member) .
                        ?member SO:familyName ?familyName .
                    }
                    order by (?pos)
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <!-- The Solr 'investigator' field is the last name of the creators. This is the same as Solr 'authorLastName'. -->
    <bean id="schema_org_creator_last_name" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="investigator" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
                    PREFIX SO:  <http://schema.org/>

                    SELECT (?familyName as ?investigator)
                    WHERE {
                        ?dsId rdf:type SO:Dataset .
                        ?dsId SO:creator ?list .
                        ?list list:index (?pos ?member) .
                        ?member SO:familyName ?familyName .
                    }
                    order by (?pos)
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_funder_identifier" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="funderIdentifier" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        (?identifier as ?funderIdentifier)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId SO:funder ?funderId .
                        ?funderId SO:identifier ?identifier .
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>


    <bean id="schema_org_funder_name" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="funderName" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        (?name as ?funderName)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId SO:funder ?funderId .
                        ?funderId SO:name ?name .
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_creator_list" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="origin" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
                PREFIX SO:   <http://schema.org/>

                SELECT (?name as ?origin)
                WHERE {
                    ?dsId rdf:type SO:Dataset .
                    ?dsId SO:creator ?list .
                    ?list list:index (?pos ?member) .
                    ?member SO:name ?name .
                }
                order by (?pos)
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_prov_hadDerivation" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_hasDerivations" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT ( str(?derivations) as ?prov_hasDerivations )
                    WHERE {
                      ?datasetId rdf:type SO:Dataset .
                      ?datasetId PROV:hadDerivation ?derivations .
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <!-- Extract 'SO:hasPart' properties from the top level 'SO:Dataset' property -->
    <bean id="schema_org_hasPart" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="hasPart" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>
                    SELECT ?hasPart
                    WHERE {
                      ?datasetId rdf:type SO:Dataset .
                      {
                        ?datasetId SO:hasPart ?node .
                        ?node      rdf:type   SO:Dataset .
                        ?node      SO:name    ?hasPart .
                      }
                      UNION
                      {
                        ?datasetId SO:hasPart ?hasPart .
                        # SO:Dataset can also appear as a sub-element of the 'SO:hasPart'
                        # so exclude those from the query result.
                        FILTER NOT EXISTS { ?hasPart rdf:type SO:Dataset . }
                      }
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

   <bean id="schema_org_keywords" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="keywords" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?keywords
                      WHERE {
                        ?datasetId rdf:type    SO:Dataset .
                        ?datasetId SO:keywords ?keywords .
                      }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_license_url" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="licenseUrl" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?licenseUrl
                      WHERE {
                        ?datasetId rdf:type    SO:Dataset .
                        ?datasetId SO:license ?license .
                        # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                        FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                        {
                            BIND(STR(?license) AS ?licenseUrl) .
                        }
                        UNION
                        {
                            ?license rdf:id ?licenseUrl .
                        }
                        UNION
                        {
                            ?license SO:license ?licenseUrl .
                        }
                      }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_license_name" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="licenseName" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?licenseName
                      WHERE {
                        ?datasetId rdf:type    SO:Dataset .
                        ?datasetId SO:license ?license .
                        # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                        FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                        {
                            BIND(STR(?license) AS ?licenseName) .
                        }
                        UNION
                        {
                            ?license SO:name ?licenseName .
                        }
                      }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <!-- Extract bounding box coordinates from a 'SO:spatialCoverage' property. -->
    <bean id="schema_org_geoShape_box_south" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="southBoundCoord" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?southBoundCoord
                      WHERE {
                        ?datasetId rdf:type           SO:Dataset .
                        ?datasetId SO:spatialCoverage ?spatial .
                        ?spatial   rdf:type           SO:Place .
                        ?spatial   SO:geo             ?geo .
                        ?geo       rdf:type           SO:GeoShape .
                        ?geo       SO:box             ?box .
                        # Extract south coord, replacing commas and multiple whitespaces to single whitespaces
                        # to simplify parsing
                        bind(strbefore(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?southBoundCoord)
                      }
                      limit 1
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="solrLatitudeConverter" />
    </bean>

    <!-- Extract bounding box coordinates from a 'SO:spatialCoverage' property. -->
    <bean id="schema_org_geoShape_box_west" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="westBoundCoord" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?westBoundCoord
                      WHERE {
                        ?datasetId rdf:type           SO:Dataset .
                        ?datasetId SO:spatialCoverage ?spatial .
                        ?spatial   rdf:type           SO:Place .
                        ?spatial   SO:geo             ?geo .
                        ?geo       rdf:type           SO:GeoShape .
                        ?geo       SO:box             ?box .
                        bind(strbefore(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?southBoundCoord)
                        bind(strafter(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?rest)
                        bind(strbefore(str(?rest), " ") as ?westBoundCoord)
                      }
                      limit 1
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="solrLongitudeConverter" />
    </bean>

    <!-- Extract bounding box coordinates from a 'SO:spatialCoverage' property. -->
    <bean id="schema_org_geoShape_box_north" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="northBoundCoord" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?northBoundCoord
                      WHERE {
                        ?datasetId rdf:type           SO:Dataset .
                        ?datasetId SO:spatialCoverage ?spatial .
                        ?spatial   rdf:type           SO:Place .
                        ?spatial   SO:geo             ?geo .
                        ?geo       rdf:type           SO:GeoShape .
                        ?geo       SO:box             ?box .
                        bind(strbefore(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?southBoundCoord)
                        bind(strafter(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?rest)
                        bind(strbefore(str(?rest), " ") as ?westBoundCoord)
                        bind(strafter(str(?rest), " ") as ?rest2)
                        bind(strbefore(str(?rest2), " ") as ?northBoundCoord)
                      }
                      limit 1
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="solrLatitudeConverter" />
    </bean>

    <!-- Extract bounding box coordinates from a 'SO:spatialCoverage' property. -->
    <bean id="schema_org_geoShape_box_east" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="eastBoundCoord" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?eastBoundCoord
                      WHERE {
                        ?datasetId rdf:type           SO:Dataset .
                        ?datasetId SO:spatialCoverage ?spatial .
                        ?spatial   rdf:type           SO:Place .
                        ?spatial   SO:geo             ?geo .
                        ?geo       rdf:type           SO:GeoShape .
                        ?geo       SO:box             ?box .
                        bind(strbefore(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?southBoundCoord)
                        bind(strafter(replace(str(?box), "\\s*,\\s*|\\s{2,}", " "), " ") as ?rest)
                        bind(strbefore(str(?rest), " ") as ?westBoundCoord)
                        bind(strafter(str(?rest), " ") as ?rest2)
                        bind(strbefore(str(?rest2), " ") as ?northBoundCoord)
                        bind(strafter(str(?rest2), " ") as ?eastBoundCoord)
                      }
                      limit 1
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="solrLongitudeConverter" />
    </bean>

    <!-- Extract 'SO:spatialCoverage'. This property can have several different forms, for different
         types of spatial coverage representations. if the value is simple text (i.e. not SO:Place),
         then it should be assigned to Solr 'namedLocation' field,
         e.g. '"spatialCoverage:" "Tahoe City, CA"'.
    -->
    <bean id="schema_org_spatialCoverage" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="namedLocation" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT ?namedLocation
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId SO:spatialCoverage ?namedLocation .
                        FILTER NOT EXISTS { ?namedLocation rdf:type SO:Place . }
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_temporalCoverage_begin" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="beginDate" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        # possible formats: "start/end", "start/..", "start"
                        (if(contains(?dates, "/"), strbefore(?dates, "/"), ?dates) as ?beginDate)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId SO:temporalCoverage ?dates .
                    }
                    limit 1
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="dateConverter" />
    </bean>

    <bean id="schema_org_temporalCoverage_end" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="endDate" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT
                        # possible formats: "start/end", "start/..", "start"
                        (if(contains(?dates, "/"), strafter(?dates, "/"), "") as ?endDate)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId SO:temporalCoverage ?dates .
                    }
                    limit 1
                ]]>
            </value>
        </constructor-arg>
        <property name="converter" ref="dateConverter" />
    </bean>

    <bean id="schema_org_variableMeasured" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="parameter" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:   <http://schema.org/>

                    SELECT (?variableMeasured as ?parameter)
                    WHERE {
                       ?datasetId rdf:type SO:Dataset .
                       {
                           ?datasetId SO:variableMeasured ?variable .
                           ?variable  rdf:type            SO:PropertyValue .
                           ?variable  SO:name             ?variableMeasured .
                       }
                       UNION
                       {
                           ?datasetId SO:variableMeasured ?variableMeasured .
                           FILTER NOT EXISTS { ?parameter rdf:type SO:PropertyValue . }
                       }
                   }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_version" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="edition" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    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/>

                    SELECT ( str(?version) as ?edition )

                    WHERE {
                        ?datasetId rdf:type schema:Dataset .
                        ?datasetId schema:version ?version .
                    }
                    limit 1
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <!-- The prov_wasDerivedFrom relationship can be obtained from either the source "SO:isBasedOn" or
         "PROV:wasDerivedFrom" relationships, which are considered equivalent. -->
    <bean id="schema_org_prov_wasDerivedFrom" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_wasDerivedFrom" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT DISTINCT
                        ( str(?wasDerivedFrom) as ?prov_wasDerivedFrom )
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        {
                            ?datasetId SO:isBasedOn ?wasDerivedFrom .
                        }
                        UNION
                        {
                            ?datasetId PROV:wasDerivedFrom ?wasDerivedFrom .
                        }
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_prov_usedByExecution" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_usedByExecution" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT ( str(?executionId) as ?prov_usedByExecution)
                    WHERE {
                      ?datasetId rdf:type SO:Dataset .
                      ?datasetId PROV:wasUsedBy ?executionId .
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_prov_usedByProgram" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_usedByProgram" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT ( str(?plan) as ?prov_usedByProgram)
                    WHERE {
                      ?datasetId rdf:type SO:Dataset .
                      ?datasetId PROV:wasUsedBy ?executionId .
                      ?executionId PROV:hadPlan ?plan.
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_prov_wasGeneratedByExecution" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_generatedByExecution" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT ( str(?executionId) as ?prov_generatedByExecution)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId PROV:wasGeneratedBy ?executionId
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_prov_wasGeneratedByPlan" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_generatedByProgram" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT
                        ( str(?planId ) as ?prov_generatedByProgram)
                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        ?datasetId PROV:wasGeneratedBy ?executionId .
                        ?executionId PROV:hadPlan ?planId
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_prov_instanceOfClass" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="prov_instanceOfClass" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX SO:   <http://schema.org/>
                    PREFIX PROV: <http://www.w3.org/ns/prov#>
                    PREFIX PROVONE: <http://purl.dataone.org/provone/2015/01/15/ontology#>

                    SELECT DISTINCT
                      ( str(?instanceType ) as ?prov_instanceOfClass )
                    WHERE {
                      ?datasetId rdf:type SO:Dataset .
                      {
                        ?datasetId PROV:wasGeneratedBy ?executionId .
                        bind ( PROVONE:Data as ?instanceType )
                      }
                      UNION
                      {
                        ?datasetId PROV:wasUsedBy ?executionId .
                        bind ( PROVONE:Data as ?instanceType )
                      }
                    }
                ]]>
            </value>
        </constructor-arg>
    </bean>

    <bean id="schema_org_url" class="org.dataone.cn.indexer.annotation.SparqlField">
        <constructor-arg name="name" value="serviceEndpoint" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
                    PREFIX rdfs:    <http://www.w3.org/2000/01/rdf-schema#>
                    PREFIX SO:  <http://schema.org/>

                    SELECT ( str(?url) as ?serviceEndpoint )

                    WHERE {
                        ?datasetId rdf:type SO:Dataset .
                        {
                          ?datasetId SO:url ?url .
                          # Don't include referenced sub-Datasets (i.e. a Dataset in a 'hasPart' property)
                          FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                        }
                        UNION
                        {
                          ?datasetId SO:distribution ?distribution .
                          ?distribution rdf:type SO:DataDownload .
                          ?distribution SO:contentUrl ?url .
                          FILTER NOT EXISTS { ?id SO:hasPart ?datasetId . }
                        }
                    }    
                ]]>
            </value>
        </constructor-arg>
    </bean>
    
    <!-- define the base and components for accessing multiple bounding coordinates for geohash -->
    <bean id="SO.geohashBase" class="org.dataone.cn.indexer.parser.utility.ElementCombiner"
        p:name="geohashBase"
        p:template="[northBoundCoord] [southBoundCoord] [eastBoundCoord] [westBoundCoord]">
        <property name="elements">
            <map>
                <entry key="northBoundCoord" value-ref="schema_org_geoShape_box_north"/>
                <entry key="southBoundCoord" value-ref="schema_org_geoShape_box_south"/>
                <entry key="eastBoundCoord" value-ref="schema_org_geoShape_box_east"/>
                <entry key="westBoundCoord" value-ref="schema_org_geoShape_box_west"/>
            </map>
        </property>
    </bean>

    <!-- use the root to calculate different geohash lengths -->
	<bean id="schema_org_geohash_1" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_1" />
		<property name="converter" ref="geohashConverter_1"/>
	</bean>
	
	<bean id="schema_org_geohash_2" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_2" />
		<property name="converter" ref="geohashConverter_2"/>
	</bean>
	
	<bean id="schema_org_geohash_3" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_3" />
		<property name="converter" ref="geohashConverter_3"/>
	</bean>
	
	<bean id="schema_org_geohash_4" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_4" />
		<property name="converter" ref="geohashConverter_4"/>
	</bean>
	
	<bean id="schema_org_geohash_5" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_5" />
		<property name="converter" ref="geohashConverter_5"/>
	</bean>
	
	<bean id="schema_org_geohash_6" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_6" />
		<property name="converter" ref="geohashConverter_6"/>
	</bean>
	
	<bean id="schema_org_geohash_7" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_7" />
		<property name="converter" ref="geohashConverter_7"/>
	</bean>
	
	<bean id="schema_org_geohash_8" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_8" />
		<property name="converter" ref="geohashConverter_8"/>
	</bean>

	<bean id="schema_org_geohash_9" class="org.dataone.cn.indexer.parser.DerivedSolrField"
		p:multivalue="true"
		p:base-ref="SO.geohashBase">
		<constructor-arg name="name" value="geohash_9" />
		<property name="converter" ref="geohashConverter_9"/>
	</bean>
    <bean id="schema_org_fullText" class="org.dataone.cn.indexer.annotation.SparqlField"
        p:multivalue="false"
        p:concatValues="true"
        p:separator=" ">
        <constructor-arg name="name" value="text" />
        <constructor-arg name="query">
            <value>
                <![CDATA[
                    PREFIX SO:   <http://schema.org/>
                    PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
                    SELECT DISTINCT (str(?string) as ?text)
                    WHERE {
                        {
                            ?a ?b ?string .
                            filter(datatype(?string) = xsd:string) .
                        }
                        UNION
                        {
                            ?a ?b ?string .
                            filter(datatype(?string) = SO:HTML) .
                        }
                   }
                ]]>
           </value>
        </constructor-arg>
    </bean>
</beans>