<resource schema="ivoidval">
	<meta name="creationDate">2015-05-27T12:36:00</meta>
	<meta name="schema-rank">500</meta>
	<meta name="title">Validator for IVOA Identifiers</meta>
	<meta name="description" format="rst">
	A validator for IVOA identifiers, checking
	conformity to version 2 of the specification.

	The service returns results in a tabular format, where an identifier is
	valid if no row with msg_type="ERROR" is present.
	
	As per DALI, the format of the table returned can be controlled
	through the RESPONSEFORMAT parameter; for machine consumption, the
	most useful values for that parameter are probably json and votable.

	The code used here is available at
	http://svn.ari.uni-heidelberg.de/svn/gavo/hdinputs/ivoidval
	</meta>

	<meta name="subject">virtual-observatories</meta>

	<meta name="creator">Markus Demleitner</meta>

	<table id="validation">
		<column name="msg_type" type="text"
			tablehead="Message Type"
			description="Type of the message; an identifier is invalid if there
				is at least one row with ERROR in this column."
			verbLevel="1">
			<values>
				<option>ERROR</option>
				<option>WARNING</option>
				<option>INFO</option>
			</values>
		</column>
		<column name="issue_code" type="text"
			tablehead="Code"
			description="Code for warnings or errors for machine consumption."
			verbLevel="1"/>
		<column name="message" type="text"
			tablehead="Content"
			description="Human-readable message content."
			verbLevel="1"/>
	</table>

	<service id="val" allowed="form,api">
		<meta name="shortName">ivoid val</meta>

		<meta name="_example" title="Valid IVOID">
			IVOA identifers without query or fragment ("Registry reference")
			must resolve to
			Registry records.  For instance,
			:genparam:`uri(ivo://org.gavo.dc/ivoidval/q/val)` is the (valid) ivoid of
			this service.
		</meta>

		<meta name="_example" title="Registry references not resolving are bad">
			A Registry reference like :genparam:`uri(ivo://example.org/does/not/exist)`
			is invalid because it does not resolve to a record in the VO
			Registry.
		</meta>

		<meta name="_example" title="No percent encoding in Registry references">
			:genparam:`uri(ivo://example.org/%64oes/not/exist)`
			is not an IVOID as percent-encoding is not allowed in either
			authority or the resource key.
		</meta>

		<meta name="_example" title="Dataset identifier">
			Publisher dataset identifiers have a query part, but the
			Registry reference still has to resolve:
			:genparam:`uri(ivo://org.gavo.dc/~?feros/data/f89411.vot)`
		</meta>

		<meta name="_example" title="Standard identifier">
			New-style standardIds use fragments to refer to standard keys within
			vstd:Standard records, as in
			:genparam:`uri(ivo://org.gavo.dc/std/glots#tables-1.0)`
		</meta>

		<meta name="_example" title="Query part and frament identifier">
			With Identifiers 2 PubDIDs, one can reference things within
			suitable datasets; in the case of
			:genparam:`uri(ivo://org.gavo.dc/~?feros/data/f89411.vot#spectral)`,
			the PubDID references a VOTable (which you can inspect at
			http://dc.zah.uni-heidelberg.de/getproduct/feros/data/f89411.vot), and
			the fragment is an ID within that file.
		</meta>

		<publish render="form" sets="local,ivo_managed"/>
		<publish render="api" sets="ivo_managed"/>

		<customCore module="bin/validator">
			<inputTable>
				<inputKey name="uri" type="text"
					tablehead="IVOID"
					description="The IVOA Identifier to validate"/>
			</inputTable>

			<outputTable id="validation_results">
				<column name="msg_type" type="text"
					tablehead="Message Type"
					description="Type of the message; an identifier is invalid if there
						is at least one row with ERROR in this column."
					verbLevel="1">
					<values>
						<option>ERROR</option>
						<option>WARNING</option>
						<option>INFO</option>
					</values>
				</column>
				<column name="message" type="text"
					tablehead="Content"
					description="Human-readable message content."
					verbLevel="1"/>
				<column name="issue_code" type="text"
					tablehead="Code"
					description="Code for warnings or errors for machine consumption."
					verbLevel="1"/>
			</outputTable>
		</customCore>
		<FEED source="//pql#DALIPars"/>
	</service>

	<table id="dids">
		<meta name="description">A set of access URLs derived from a
		publisher DID</meta>
		<!-- this is used from within didresolver.py -->
		<column name="rec_type" type="text"
			tablehead="Record Type"
			description="Type of the record (ERROR, WARNING, or RESULT)."
			verbLevel="1">
			<values>
				<option>ERROR</option>
				<option>WARNING</option>
				<option>RESULT</option>
			</values>
		</column>
		<column name="message" type="text"
			tablehead="Content"
			description="Human-readable message content."
			verbLevel="1"/>
		<column name="access_uri" type="text"
			tablehead="URI"
			description="For result records, the URI of the dataset."
			verbLevel="1"
			displayHint="type=url"/>
	</table>

	<data id="import_dids">
		<dictlistGrammar/>
		<make table="dids">
			<rowmaker idmaps="*"/>
		</make>
	</data>

	<service id="didresolve" allowed="form,api">
		<meta name="shortName">pubDID resolver</meta>

		<publish render="form" sets="local,ivo_managed"/>
		<publish render="api" sets="ivo_managed"/>

		<meta name="title">Global PubDID resolver</meta>

		<meta name="description" format="rst">
			This service implements the Identifiers 2.0
			suggestion for how to resolve an IVOA publisher dataset identifier;
			that is, it tries to resolve the registry part to Datalink,
			SSAP, or Obscore capabilities and tries those to find access URLs.
			If that fails, it repeats this procedure for services that the
			base resource declares as served-by.

			The code used here is available at
			http://svn.ari.uni-heidelberg.de/svn/gavo/hdinputs/ivoidval.

			See also Examples_

			.. _Examples: http://dc.g-vo.org/ivoidval/q/didresolve/examples
		</meta>

		<meta name="_example" title="Resolution in Datalink">
			The preferred way to resolve PubDIDs is in a Datalink_ service.
			If the datalink document returned contains one or more rows with
			``#this`` semantics, the corresponding access URLs are returned,
			as for
			:genparam:`pub_did(ivo://org.gavo.dc/~?flashheros/data/taut/f0691.mt)`,

			.. _Datalink: http://ivoa.net/documents/DataLink
		</meta>

		<meta name="_example" title="Resolution in Obscore">
			As with
			:genparam:`pub_did(ivo://org.gavo.dc/tap?mlqso/data/slits/BRI0952_data.fits)`,
			PubDIDs with a registry part pointing to a TAP service will be
			looked for in that TAP service's ``ivoa.obscore`` table (we don't
			bother checking if it exists, so this service does not distinguish
			between a service without obscore and a service with an obscore table
			that just doesn't have the PubDID in question.
		</meta>

		<meta name="_example" title="Resolution in SSAP">
			:genparam:`pub_did(ivo://org.gavo.dc/feros/q/ssa?f04031.bdf)`,
			is an example for a PubDIDs that has an SSAP service in its registry
			part.  For those, the resolver tries passing in the id through
			SSAP's PUBDID parameter; if the service isn't broken, that should
			yield at least one access URL.  Note that in the example, two different
			files are returned, which are representations of the same data set
			in two formats.
		</meta>

		<meta name="_example" title="Resolution through relationships">
			To enable pure data collections or architectures with central, say,
			datalink services, the resolution process looks at services that
			the service referenced in the pubDID's registry part declares itself
			to be ``served-by``.  By default, this only happens if the other
			means of obtaining a result have failed.  You can, however, pass
			:genparam:`force_related(True)` to go through relationship even
			in the presence of results.

			This is necessary for
			:genparam:`pub_did(ivo://org.gavo.dc/apo/res/apo/frames?apo/cd/9506/L2237_950602_r_01.fits)`,
			as it has an (auxiliary) TAP capabilty itself.  When forced
			to go through the related services, the resolver will hit the
			TAP service a second time, as the TAP service's main record
			is in a served-by relationship (as you can see in its
			`resource record`_

			.. _resource record: http://dc.zah.uni-heidelberg.de/rr/q/pmh/pubreg.xml?verb=GetRecord&amp;metadataPrefix=ivo_vor&amp;identifier=ivo%3A%2F%2Forg.gavo.dc%2Fapo%2Fres%2Fapo%2Fframes
		</meta>


		<customCore module="bin/didresolver">
			<inputTable>
				<inputKey name="pub_did" type="text" required="True"
					tablehead="Pub. DID"
					description="An Identifiers 2.0-compliant IVOA publisher DID;
						see ../examples for what you can put here">
					<property name="defaultForForm">ivo://org.gavo.dc/tap?mlqso/data/slits/BRI0952_data.fits</property>
				</inputKey>
				<inputKey name="force_related" type="boolean"
					tablehead="Force related services?"
					description="Setting this to a true value will make the service
						look at served-by services of the host resource and
						attempt to resolve there, too"/>
			</inputTable>
			<outputTable original="dids"/>
		</customCore>
	</service>

	<regSuite title="ivoidval regression">
		<regTest title="ivoid API/json delivers errors.">
			<url uri="ivo://bad.stuff/not%20allowed!"
				RESPONSEFORMAT="json">val/api</url>
			<code>
				import json
				msgs = set(tuple(r) for r in json.loads(self.data)["data"])
				self.assertTrue(
					('INFO', 'Validating as a Registry reference', None)
					in msgs, "info missing")
				self.assertTrue(
					('WARNING', 'Sub-delimiter found in resource key; this ivoid must'
						' only be used with specialised clients', None) in msgs,
						"sub-delimiter warning missing")
				self.assertTrue(
					('ERROR', 'Registry reference missing in registry', '8.4') in msgs,
					"registry reference error message missing")
				self.assertTrue((u'INFO', u'ivo-id is invalid', None) in msgs,
					"invalidity diagnosis missing")
			</code>
		</regTest>

		<regTest title="ivoid form reports success">
			<url uri="ivo://org.gavo.dc" parSet="form">val/form</url>
			<code><![CDATA[
				self.assertHasStrings("<td>Validating as an authority ID</td>")
				self.assertHasStrings("<td>ivo-id is valid</td>")
			]]></code>
		</regTest>
	</regSuite>
</resource>
