<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html
    xmlns="http://www.w3.org/1999/xhtml"
    xml:lang="en"
    version="XHTML+RDFa 1.0"
    xmlns:addthis="http://www.addthis.com/help/api-spec"
    xmlns:fb="http://www.facebook.com/2008/fbml"
>
<?vsp
--
--
--  $Id$
--
--  This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
--  project.
--
--  Copyright (C) 1998-2018 OpenLink Software
--
--  This project is free software; you can redistribute it and/or modify it
--  under the terms of the GNU General Public License as published by the
--  Free Software Foundation; only version 2 of the License, dated June 1991.
--
--  This program is distributed in the hope that it will be useful, but
--  WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--  General Public License for more details.
--
--  You should have received a copy of the GNU General Public License along
--  with this program; if not, write to the Free Software Foundation, Inc.,
--  51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
--

--
-- Registry keys:
--
-- fct_timeout_max - anytime query timeout for producing this page
-- fct_addthis_key - addthis.com API key
-- fct_license_text - markup designating a license for content on site
--


  declare _G, _S, odd_position any;
  declare page_resource_uri, proxy_iri, rdf_link, label, vlbl, _subject any;
  declare white_page, arr, data, meta, h1, h2, inx, gr, refr, sid, inf, sas, langs, best_q, grs any;
  declare urilookup integer;
  declare dbg_enable varchar;
  declare qry_str varchar;
  declare dbg_out any;
  declare inf_parm varchar;
  declare ses_parms varchar;
  declare all_langs, lang_parm any;
  declare c_iri, iri_type, iri_type_label, _F, _from, topof varchar;
  declare page, n_per_page, lim, ofs, dis_next, deadl int;
  declare vis, printed, _skip, _last int;
  declare all_lang any;
  declare curr_pred any;
  declare dt1, dt2, count_str, tbinf, tbsas, ua, doc, sp_mode, sp_accept, view_mode varchar;
  declare c_iri_a any;
  declare gs_user_id, gs_check_needed integer;
  declare gs_check_cond varchar;
  declare sponge_request, graph_perms, graph_perms_allow_sponge int;
  declare host varchar;
  declare pageUrl, err varchar;
  declare dist int;
  declare stat, msg varchar;
  declare metas, rset any;
  declare auto_sponge_on_empty_graph int;

  if (registry_get ('fct_auto_sponge') = '1')
    auto_sponge_on_empty_graph := 1;
  err := null;

  deadl := 0;

  declare exit handler for sqlstate '40001' {
    rollback work;
    if (deadl < 5) 
      goto again;	
    resignal;
  };
  -- XXX: disabled
  --declare continue handler for sqlstate 'S1TAT';
  --set result_timeout = atoi (registry_get ('fct_timeout_max'));

  host := http_request_header (http_request_header (), 'X-Forwarded-Host', null, null);
  if (host is null)
    host := http_request_header (http_request_header (), 'Host');

again:
  n_per_page := 100;
  dis_next := 0;
  dbg_enable := get_keyword ('dbg', params);
  if (dbg_enable = '1')
    {
        dbg_printf ('Enabling b3s session debug.\n');
        connection_set ('b3s_dbg', 1);
        dbg_out := string_output ();
    }
  else connection_set ('b3s_dbg',0);

  dist := atoi (get_keyword ('distinct', params, '1'));
     
  connection_set ('ns_ctr', 1); /* for unknown xmlns to print in RDFa */

  white_page := 1;
  sid := null;
  inf := '';

  sp_mode := 'add';

  if (__proc_exists ('DB.DBA.lp_score_ck') is not null)
    DB.DBA.lp_score_ck (lines);
  b3s_handle_ses (path, lines, params);
  sid := connection_get ('sid');

  b3s_parse_inf (sid, params);
  inf := b3s_render_inf_clause ();
  tbinf := connection_get ('inf');
  tbsas := connection_get ('sas');
  if (tbinf is not null)
    tbinf := sprintf ('TABLE OPTION (WITH \'%s\')', tbinf);
  else
    tbinf := '';

  if (tbsas is not null)
    tbsas := '';
  else
    tbsas := '';


  --
  -- Get AddthisKey from registry
  --
  --  if 0 then disable addthis support
  --  if 1 use temp key to get basic social bookmarking
  --  any other value should be a registered key
  --
  declare _addthis_key varchar;
  _addthis_key := registry_get ('fct_addthis_key');
  if (not isstring(_addthis_key)) _addthis_key := '0';
  if ('1' = _addthis_key) _addthis_key := 'xa-4ce13e0065cdadc0';


  langs := http_request_header_full (lines, 'Accept-Language', 'en');
  ua :=   http_request_header (lines, 'User-Agent');
  all_langs := b3s_get_lang_acc (lines);
  lang_parm := get_keyword ('lang', params, '');
  if (length (lang_parm))
    {
      all_langs := vector (lang_parm, 1.0);
      langs := lang_parm;
    }
  gr := get_keyword ('g', params, '');
  gr := replace (gr, ' ', '%20');

  _F := ''; _from := null;
  grs := connection_get ('graphs', null);
  ses_parms := b3s_render_ses_params ();
  if (grs is not null)
    {
      foreach (any x in grs) do
	{
          x := replace (x, ' ', '%20');
	  _F := _F || sprintf (' FROM <%s> ', x);
	}
    }


  page := null;

   _last := atoi (get_keyword ('lp', params, '0'));
  if ({?'prev'} is not null)
    page := atoi (get_keyword ('op', params, '0'));
  else if ({?'first'} is not null)
    page := 0;
  else if ({?'last'} is not null)
    page := _last;
  else if ({?'next'} is not null)
    page := atoi (get_keyword ('p', params, '0'));
  else if ({?'go'} is not null)
    page := atoi (get_keyword ('gp', params, '1')) - 1;
  else
    page := atoi (get_keyword ('p', params, '1')) - 1;
  --topof := '';
  b3s_dbg_out (dbg_out, 'sid     : ' || sid);
  b3s_dbg_out (dbg_out, 'gr      : ' || gr);

  arr := rfc1808_parse_uri (gr);

  if (gr[0] <> '#'[0] and arr[0] = '' and arr[1] = '' and arr[2] <> '')
    gr := 'http://' || gr;

  arr := rfc1808_parse_uri (gr);
  arr [5] := '';
  doc := vspx_uri_compose (arr);
  if (arr[0] = 'nodeID')
    doc := rtrim (doc, '/');
  if (gr[0] = '#'[0])
    doc := gr;

  sponge_request := 0;
  if (get_keyword ('sp', params) = '1' or get_keyword ('sr', params) is not null or get_keyword ('sponger:get', params) is not null)
    sponge_request := 1;

  _G := b3s_get_entity_graph (doc, sponge_request);
  page_resource_uri := gr;
  -- page_resource_uri := replace (page_resource_uri, '%23', '#');
  page_resource_uri := replace (page_resource_uri, ' ', '%20');
  page_resource_uri := replace (page_resource_uri, '"', '%22');
  __box_flags_set (page_resource_uri, 2);

  _S := page_resource_uri;
  proxy_iri := page_resource_uri;

  b3s_dbg_out (dbg_out, 'page_resource_uri: ' || page_resource_uri);
  sp_mode := get_keyword ('sponger:get', params, 'add');
  sp_accept := get_keyword ('sponger:accept', params, '');
  if (length (sp_accept))
    sp_accept := 'define get:accept "' || sp_accept || '"';

  -- check ACL
  if (sponge_request)
    if (__proc_exists ('DB.DBA.RDF_SPONGE_AUTH_SI') is not null and 0 = DB.DBA.RDF_SPONGE_AUTH_SI ('Virtuoso Sponger'))
      {
        http_rewrite ();
        http_status_set (403);
        http ('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">');
        http (sprintf ('<html><body>Use of this service is not allowed for your current WebID: %V</body></html>', connection_get ('WebID', '<none>')));
        return;  
      } 

  -- The var "pageUrl" is also used in the fct_val_login_status.vsp include below
  pageUrl := FCT.DBA.build_page_url_on_current_host ('/describe/', sprintf ('url=%U%s', gr, FCT.DBA.get_describe_request_params (params)));

  graph_perms_allow_sponge := sponge_request;
  view_mode := 'full';
  graph_perms := b3s_get_user_graph_permissions (_G, pageUrl, sponge_request, 0, NULL, NULL, graph_perms_allow_sponge, view_mode); 
  if (view_mode = 'none')
  {
    -- User doesn't have read permission
    return;
  }

  if (graph_perms_allow_sponge)
  {
    declare sp_done int;
    sp_done := 0;
    declare exit handler for sqlstate 'RDF*'
    {
      err := __SQL_MESSAGE;
      rollback work;
      goto errend; 
    };

  -- if (get_keyword ('sp', params) = '1' and 0 = length (_F))
  if (get_keyword ('sp', params) = '1')
    {
      DB.DBA.EXEC_AS (sprintf ('sparql define get:error-recovery "signal" define input:storage "" define get:soft "add" SELECT * from <%s> where { ?x ?y ?z . }', _G), 'SPARQL', 1);
      DB.DBA.VT_INC_INDEX_DB_DBA_RDF_OBJ ();
      sp_done := 1;
    }
  -- else if ((get_keyword ('sr', params) is not null or get_keyword ('sponger:get', params) is not null) and 0 = length (_F))
  else if ((get_keyword ('sr', params) is not null or get_keyword ('sponger:get', params) is not null))
    {
      declare refr varchar;
      if (get_keyword ('sr', params, '') = 'clean')
	{
	  refr := 0;
	  if (exists (select 1 from SYS_HTTP_SPONGE where HS_ORIGIN_URI = doc))
	    {
	      -- Checks whether any Sponger ACLs will prevent sponging, even if the user's graph permissions allow it. 
              -- if (SPONGING_ALLOWED())  -- only available on develop/7.x branch
	      {
		-- We're user SPARQL at this point
		DB.DBA.EXEC_AS (sprintf ('sparql clear graph <%s>', _G), 'dba');
	      }
            }
        }
      else
        refr := atoi (get_keyword ('sr', params, '0'));

      DB.DBA.EXEC_AS (sprintf ('sparql define get:error-recovery "signal" define input:storage "" define get:refresh "%d" define get:soft "%s" %s SELECT * from <%s> where { ?x ?y ?z . }', refr, sp_mode, sp_accept, _G), 'SPARQL', 1);
      DB.DBA.VT_INC_INDEX_DB_DBA_RDF_OBJ ();
      sp_done := 1;
    }
    errend:;
    if (sp_done)
      {
        http_status_set (302);
	http_header (sprintf ('Location: /describe/?url=%U%s\r\n', _G, ses_parms));
        return;
      }
  }
  --set_user_id (http_map_get ('vsp_uid'));

  odd_position := 0;
  set http_charset='utf-8';
  set isolation = 'uncommitted';

  http_header ('Cache-Control: no-cache, must-revalidate\r\nPragma: no-cache\r\n');
  label := ''; _subject := '';

  label := b3s_label (_S, langs);

  if (iswidestring (label))
    vlbl := label;
  else
    vlbl := charset_recode (label, 'UTF-8', '_WIDE_');
  if (vlbl = 0)
    vlbl := charset_recode (label, current_charset (), '_WIDE_');
  if (vlbl = 0)
    vlbl := label; 

  b3s_dbg_out (dbg_out, 'label: "' || vlbl || '"');

  declare types_a, types_b any;
  declare e_type any;
  declare e_type_label varchar;
  declare e_type_a any;

--  dbg_printf ('_S:%s', _s); 

  types_a := b3s_get_types (_S, _F, langs);
  types_b := b3s_get_all_types (_S, _F, langs);

--  dbg_obj_print (types_a);

  e_type_a := b3s_choose_e_type (types_b);

--  dbg_obj_print (e_type_a);

  e_type := e_type_a[0];
  e_type_label := e_type_a[1];
  
  qry_str := sprintf ('sparql %s prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> prefix dc: <http://purl.org/dc/elements/1.1/> select ?o (lang(?o)) %s where { <%s> rdfs:comment ?o }', inf, _F, _S);

--    dbg_obj_print (qry_str);

  b3s_dbg_out (dbg_out, 'qry: ' || qry_str);

  exec (qry_str, null, null, vector (), 0, meta, data);

  _subject := b3s_label_get (data, langs);

  rdf_link := sprintf ('/sparql?query=%U', __box_flags_tweak (sprintf ('define sql:describe-mode "CBD" %s DESCRIBE <%s>', b3s_render_inf_clause(), _S), 2)); 
  __box_flags_set (rdf_link, 2);

  declare __res_desc, qs, qv, best_variant, accept varchar;
  declare best_q, curr float;
  declare inx int;

  accept := http_request_header_full (lines, 'Accept', 'text/html');
  if (accept = '*/*')
    accept := 'text/html';
  -- accepted types
  qs := vector ('text/html', 'application/xhtml+xml', 'text/n3', 'text/turtle', 'application/rdf+xml', 'application/json', 'text/plain');
  -- quality prefs
  qv := vector (        0.5,                     0.7, 	    0.8,           0.8,                   1.0,                0.7,          0.1);
  best_q := 0;
  best_variant := null;
  inx := 0;
  foreach (varchar q in qs) do
    {
      curr := DB.DBA.URLREWRITE_CALC_QS (accept, q);
      curr := curr;
      if (best_q < curr)
        {
	  best_q := curr;
	  best_variant := q;
	}
      inx := inx + 1;
    }
  if (best_variant is null)
    {
      http_rewrite ();
      http_status_set (406);
      http_header ('Alternates: ');
      http_header (http_header_get () || sprintf ('{ "http://%{WSHost}s/describe/?url=%U" 0.5 {type text/html}}', gr));
      inx := 0;
      foreach (varchar q in qs) do
        {
	  if (q  not in ('text/html', 'application/xhtml+xml'))
	    http_header (http_header_get () || sprintf (', { "http://%{WSHost}s%s&format=%U" %.2f {type %s}}', rdf_link, q, qv[inx], q));
          inx := inx + 1;
	}
      http_header (http_header_get () || '\r\n');
      return;
    }
  if (best_variant is not null and best_variant not in ('text/html', 'application/xhtml+xml'))
    {
      http_rewrite ();
      http_status_set (303);
      http_header (sprintf ('TCN: choice\r\nVary: negotiate,accept\r\nLocation: http://%{WSHost}s%s&format=%U\r\n', rdf_link, best_variant));
      return;
    }
  __res_desc := b3s_uri_curie(page_resource_uri);
  fct_links_hdr (_S, rdf_link);
  if (not length (label))
    label := b3s_trunc_uri (page_resource_uri);
  if (vlbl <> 0) label := vlbl;
  declare desc_resource_uri varchar;
  declare desc_qr varchar;
  desc_qr := sprintf ('define sql:describe-mode "SPO" DESCRIBE <%s>', page_resource_uri);
  desc_resource_uri := sprintf ('http://%{WSHost}s/sparql?query=%U&format=cxml', desc_qr);
  --http_flush (1);

  declare plink_href varchar;

  plink_href := sprintf ('/describe/?url=%U', b3s_u2w (page_resource_uri));

  if (page is not null and page > 0)
    {
      plink_href := concat (plink_href, sprintf ('&gp=%d&go=', page+1));
    }
  if (connection_get ('inf') is not null)
    {
      plink_href := concat (plink_href, sprintf ('&inf=%U', connection_get ('inf')));
    }
  if (connection_get ('sas') is not null)
    {
      plink_href := concat (plink_href, sprintf ('&sas=%U', connection_get ('sas')));
    }
  if (length (grs) <> 0)
    {
      foreach (any x in grs) do
	{
	  plink_href := plink_href || sprintf ('&graph=%U', x);
	}
    }


?>
<head>
    <base href="http<?V case is_https_ctx () when 1 then 's' else '' end ?>://<?V host ?>/fct/rdfdesc/" />
    <title>About: <?vsp if (length (label)) http_value (label); else http_value (b3s_uri_curie (page_resource_uri));?></title>
    <!--link rel="alternate" type="application/rdf+xml" href="<?=rdf_link?>" title="RDF" /-->

    <?vsp
	declare main_ss varchar;
        main_ss := registry_get ('fct_main_ss');
        if (not isstring (main_ss)) main_ss := 'styles/default.css';
    ?>
    <link rel="stylesheet" type="text/css" href="<?=main_ss?>"  charset="utf-8" />

    <link rel="stylesheet" type="text/css" href="styles/highlighter.css" charset="utf-8" />
    <script type="text/javascript" >
      var featureList=["tab","ajax"];
    </script>
    <script type="text/javascript" src="/fct/oat/toolkit/loader.js"></script>
    <script type="text/javascript" src="s/description.js"></script>
<?vsp fct_links_mup (_S, rdf_link); ?>
</head>
<body>
  <div id="PG">
    <div id="HD">
    <?vsp fct_desc_page_head (); ?>
    <div id="hd_r">
    </div>
    <ul id="main_menu">
      <?vsp if (sid is not null) { ?>
        <li><a href="<?= b3s_render_fct_link() ?>">Facets</a></li>
      <?vsp } else { ?>
      <li><a href="/fct/">Facets (new session)</a></li>
      <?vsp } ?>
      <li id="mnu_descr" class="sel"><a href="/describe/?uri=<?V _S ?><?V ses_parms ?>" class="sel">Description</a></li>
      <li id="mnu_usage">
        <a href="usage.vsp?g=<?U _S ?><?V ses_parms ?>">Metadata</a>
      </li>
      <li id="mnu_settings"><a href="settings.vsp?g=<?U _S ?><?V ses_parms ?>">Settings</a>
        <div id="settings_popup" style="display: none">
          <ul>
            <li>
              <input id="sas_ckb" type="checkbox" <?= b3s_sas_selected() ?> onchange="javascript:sas_cb();"/>
              <label for="sas_ckb">owl:sameAs</label>
            </li>
            <li>
              <label for="inf_sel">Inference Rule:</label>
              <select id="inf_sel" onchange="javascript:inf_cb();"><?vsp b3s_render_inf_opts (); ?></select><br/>
            </li>
          </ul>
        </div> <!-- settings-popup -->
      </li>
    </ul>
  </div> <!-- #HD -->
  <div id="MD">
    <div class="page_resource_info">
	<h2>About: <a href="<?= case when page_resource_uri like
    'nodeID://%' then b3s_http_url (page_resource_uri) else
    page_resource_uri end ?>"><?vsp if (length(label)) http_value
    (label); else http_value(b3s_uri_curie (page_resource_uri));
    ?></a>&nbsp;&nbsp;&nbsp;<a class="desc_permalink" href="<?= case when page_resource_uri like
    'nodeID://%' then b3s_http_url (page_resource_uri) else
    page_resource_uri end ?>">Goto</a>&nbsp;<a class="desc_sponge_link"
    href="/describe/?url=<?U page_resource_uri ?><?= case when sid is
    not null then '&sid=' || sid end ?>&amp;sponger:get=add"
    title="Click to generate local descriptor data for this entity"
    id="sp_link" rel="nofollow">Sponge</a>
&nbsp;<a class="desc_permalink" href="<?vsp http (fct_make_curie (sprintf ('%s&distinct=%d',  plink_href, equ (dist, 0)), lines)); ?>" title="This link enables you toggle between normalized and un-normalized views of data using by applying or note applying a DISTINCT operator"><?vsp if (dist) http ('Not'); ?>Distinct</a>
&nbsp;<a class="desc_permalink" href="<?vsp http (fct_make_curie (sprintf ('%s&distinct=%d', plink_href, dist), lines)); ?>">Permalink</a>
    </h2>
      <div class="ds_inf_info">
	    An Entity of Type : <a href="<?V e_type ?>"><?V e_type_label ?></a>,
	    within Data Space : <a href="http://<?V host ?>"><?V host ?></a> associated with source <a href="usage.vsp?g=<?U _S ?><?V ses_parms ?>">document(s)</a><br/>
<?vsp

  declare is_class int;
  is_class := b3s_find_class_type (_S, _F, types_a);

  if (('http://www.w3.org/2002/07/owl#Thing' <> e_type and length (types_a)) or is_class) 
    {
?>
      <form id="fct_form" action="/fct/facet.vsp" method="get">
      <div>

<?vsp
        if (is_class)
          {
?>
            <input type="hidden" name="iri" value="<?V _S ?>">
<?vsp   
          }
        else 
          {
?>
            <label for="c_iri_sel">Type:</label>
<?vsp
            types_a := b3s_render_iri_select (types_a, 'name="iri" id="c_iri_sel"');
          }

        if (sid)
          { 
?>
            <input type="hidden" name="sid" value="<?V sid ?>"/>
            <label for="cmd_sel">Command:</label>
            <select name="cmd" id="cmd_sel">
              <option value="new_with_class">Start New Facet</option>
              <option value="set_class">Add To Current Facet</option>
            </select>
            <button class="fct_sel_as_type" title="">Go</button>
<?vsp
          }
        else
          {
?>
            <input type="hidden" name="cmd" value="new_with_class"/>
            <button class="fct_sel_as_type" title="">New Facet based on Instances of this Class</button>
<?vsp
          }
?>
      </div>
      </form>
<?vsp    
  }
  if (DB.DBA.VAD_CHECK_VERSION ('c_uri') is not null and __proc_exists ('QRcode encodeString8bit', 2) is not null and strcasestr (ua, 'Mobile') is null) {
?>
<?vsp } ?>
      </div>
    </div>
<?vsp
if (_subject <> '') {
?>
  <p class="subj_desc"><?vsp http (sprintf ('%s', _subject)); ?></p>
<?vsp
} else {
?>
  <p class="subj_delim"></p>
<?vsp
}
     if (err is not null)
       http_value (err, 'div');
?>
<!--            <li><a href="/fct/facet.vsp?sid=<?V sid ?>&amp;cmd=set_class&amp;iri=<?V gr ?>">Choose <?V ''?> as Type</a></li>
                <li><a href="/fct/facet.vsp?sid=<?V sid ?>&amp;cmd=open_property">Choose <?V ''?> as Property (p)</a></li>
                <li><a href="">Choose <?V ''?> as Value (o)</a></li>-->
<!-- proptable -->
    <table class="description">

<?vsp

    --  gs_user_id := USER;
    --  gs_user_id := coalesce ((select U_ID from DB.DBA.SYS_USERS where U_NAME=gs_user_id and not U_ACCOUNT_DISABLED), http_nobody_uid());
      gs_user_id := get_user_id (1);
      -- dbg_obj_princ ('user = ', USER, ', gs_user_id = ', gs_user_id);
      gs_check_needed := b3s_gs_check_needed();
      if (connection_get ('s_term') = 's')
        http ('<tr><th class="property">Properties</th><th class="value">Objects</th></tr>');
      else
        http ('<tr><th class="property">Attributes</th><th class="value">Values</th></tr>');
      all_lang := vector ('*', 1.0);
      topof := sprintf (' TOP %d, %d  ', n_per_page * page, n_per_page);
      _skip := n_per_page * page;

      if (length (_F) or 1 = sys_stat ('cl_run_local_only'))
      {
      dt1 := sprintf ('select id_to_iri ("p") as PRED, __ro2sq ("o") as OBJECT LONG VARCHAR, 0 as FLAG int from (sparql %s define output:valmode "LONG" select distinct ?p ?o %s where { <%s> ?p ?o }  order by 1) sp1', inf, _F, _S);
      }
      else
      {
        gs_check_cond := case gs_check_needed when 0 then '' else sprintf (' AND DB.DBA.RDF_GRAPH_USER_PERMS_ACK (G, %d, 1)', gs_user_id) end;
      dt1 := sprintf ('select id_to_iri ("p") as PRED, __ro2sq ("o") as OBJECT LONG VARCHAR, 0 as FLAG int from (SELECT DISTINCT p, o FROM DB.DBA.RDF_QUAD %s where s = __i2idn (\'%s\' , 1) %s ORDER BY 1 ASC OPTION (QUIETCAST %s)) sp1',
        tbinf, _S, gs_check_cond, tbsas);
      }
      dt2 := sprintf ('select id_to_iri ("p") as PRED, __ro2sq ("o") as OBJECT LONG VARCHAR, 1 as FLAG int from (sparql %s define output:valmode "LONG" select distinct ?p ?o %s where { ?o ?p <%s> } order by 1) sp2', inf, _F, _S);

      --topof := '';
      qry_str := sprintf ('select %s PRED, OBJECT, FLAG from (%s UNION ALL %s) un0', topof, dt1, dt2);
      if (dist = 0)
      qry_str := replace (qry_str, 'distinct', '');
      if (_last = 0)
        {
	  if (length (_F) or 1 = sys_stat ('cl_run_local_only'))
            {
	      dt1 := sprintf ('select count(*) as cnt from (sparql %s define output:valmode "LONG" select distinct ?p ?o %s where { <%s> ?p ?o }  order by 1) sp1', inf, _F, _S);
	    }
          else
	    {
              gs_check_cond := case gs_check_needed when 0 then '' else sprintf (' AND DB.DBA.RDF_GRAPH_USER_PERMS_ACK (G, %d, 1)', gs_user_id) end;
              dt1 := sprintf ('select count(*) as cnt from (SELECT DISTINCT p, o FROM DB.DBA.RDF_QUAD %s where s = __i2idn (\'%s\' , 1) %s ORDER BY 1 ASC OPTION (QUIETCAST %s)) sp1',
                tbinf, _S, gs_check_cond, tbsas);
	    }
	  dt2 := sprintf ('select count(*) as cnt from (sparql %s define output:valmode "LONG" select distinct ?p ?o %s where { ?o ?p <%s> } order by 1) sp2', inf, _F, _S);
	  count_str := sprintf ('select sum (cnt) from (%s UNION ALL %s) un0', dt1, dt2);
          if (dist = 0)
          count_str := replace (count_str, 'distinct', '');
          count_str := replace (count_str, 'order by 1', '');
	  -- dbg_obj_princ ('count_str = ', count_str);
	  exec (count_str, null, null, vector (), 0, meta, data);
	  if (length (data) and length (data[0]))
	    _last := data[0][0]; -- sum is supposed to have always number
          else
	    _last := n_per_page;
	  _last := _last / n_per_page;
        }

      -- dbg_obj_princ ('qry_str = ', qry_str);
      exec (qry_str, null, null, vector (), 0, null, null, h1);
      curr_pred := '';
      inx := 0;
      data := null;
      while (0 = exec_next (h1, null, null, data))
	{
           declare PRED, OBJECT, FLAG any;
	   --if (inx <= _skip)
	   --  goto nxt1;
           if (length (data) < 3)
	     goto skip;
	   pred := data[0];
           object := data[1];
           FLAG := data[2];
	   if (not length (PRED))
	     goto nxt1;

	   if (curr_pred <> pred)
	     {
               if (curr_pred <> '') http ('</ul></td></tr>');
	       b3s_http_print_l (PRED, odd_position, flag, sid, langs);
	       curr_pred := pred;
	     }
           vis := b3s_http_print_r (page_resource_uri, OBJECT, sid, PRED, langs, 1, all_langs, _from, FLAG);
	   nxt1:;
	   inx := inx + 1;
	   skip:;
	}
      exec_close (h1);
      if (curr_pred <> '') http ('</ul></td></tr>');
--      dbg_obj_print (inx);
      if (inx < n_per_page)
        dis_next := 1;

      if (odd_position = 0)
      {
	if (auto_sponge_on_empty_graph)
	{
	  -- Sponging wasn't explicitly requested in the request URL.
	  -- The view dataset is empty.
	  -- Rather than display an empty result set, force automatic sponging.

	  declare spongeUrl, protocol varchar;
	  protocol := 'http'; if (is_https_ctx()) protocol := 'https';
	  spongeUrl := sprintf ('%s://%s/describe/?url=%U&sponger:get=add&sr=clean', protocol, host, gr);

	  if (not sponge_request)
	  {
	    http_rewrite ();
	    http_status_set (303);
	    http_header (sprintf('Location: %s\r\n', spongeUrl));
	    return 0;
	  }
	}

	http_request_status ('HTTP/1.1 404 Not found');
	http ('<tr><td colspan="2"><p>No further information is available.</p></td></tr>');
      }
?>
      </table>
      <div id="nav">
	  <form action="/describe/" method="get">
	  <div>
	      <input type="hidden" name="url" value="<?V gr ?>" />
              <input type="submit" name="go" value="Go" style="width: 0px; height: 0px; margin: 0px; padding: 0px; outline: none; border: 0px;" />
	      <input type="hidden" name="distinct" value="<?V dist ?>" />
	      <?vsp if (connection_get ('inf') is not null) { ?>
	      <input type="hidden" name="inf" value="<?V connection_get ('inf') ?>" />
	      <?vsp } ?>
	      <?vsp if (connection_get ('sas') is not null) { ?>
	      <input type="hidden" name="sas" value="<?V connection_get ('sas') ?>" />
	      <?vsp } ?>
	      <input type="hidden" name="p" value="<?V page + 1 ?>"/>
	      <?vsp if (sid is not null) { ?>
	      <input type="hidden" name="sid" value="<?V sid ?>"/>
	      <?vsp } ?>
	      <?vsp if (connection_get ('graphs') is not null) { 
	          foreach (any x in grs) do {
              ?>
	      <input type="hidden" name="graph" value="<?V x ?>"/>
	      <?vsp 
	      } } ?>
	      <input type="hidden" name="lp" value="<?V _last ?>"/>
	      <?vsp if (topof <> '' and _last > 0) {  if (1 or page > 0) { ?>
	      <button type="submit" value="" name="first" <?vsp if (page <= 0) { http ('disabled="disabled"'); } ?>>&#9666;&#9666; First</button>
	      &nbsp;
	      <input type="hidden" name="op" value="<?V page - 1 ?>"/>
	      <button type="submit" value="" name="prev" <?vsp if (page <= 0) { http ('disabled="disabled"'); } ?>>&#9666; Prev</button>
	      &nbsp;&nbsp;&nbsp;
	<?vsp } if (1 or not dis_next) { ?>
	      <button type="submit" value="" name="next" <?vsp if (dis_next) { http ('disabled="disabled"'); } ?>>Next &#9656;</button>
	       &nbsp;
	      <button type="submit" value="" name="last" <?vsp if (dis_next) { http ('disabled="disabled"'); } ?>>Last &#9656;&#9656;</button>
	       &nbsp;&nbsp;&nbsp;
	       Page <?V page + 1 ?> of <?V _last + 1 ?>  &nbsp;&nbsp;&nbsp;
	       <input type="text" value="<?V page + 1 ?>" size="5" name="gp" /> &nbsp;
	       <button type="submit" value="" name="go">Go</button>
	<?vsp } } ?>
	</div>
	</form>
      </div>
    </div> <!--  #MD -->
    <?vsp b3s_render_dbg_out (dbg_out); ?>
<!-- footer -->
    <div id="FT">
	Faceted Search &amp; Find service v<?vsp http(DB.DBA.VAD_CHECK_VERSION('fct')); ?> as of <?V fct_build_info () ?><br/><br/>
<?vsp if (_addthis_key <> '0') { ?>
  <div id="FT_share">
    <!-- AddThis Button BEGIN -->
	<div class="addthis_toolbox addthis_default_style ">
	<a class="addthis_button_facebook_like" id="fb_like_id"></a>
	<a class="addthis_button_tweet"></a>
	<a class="addthis_button_google_plusone" id="g_plusone_id"></a>
	<a class="addthis_counter addthis_pill_style"></a>
	</div>
    <script type="text/javascript">
    /*<![CDATA[*/
	var addthis_config = {"data_track_clickback":true, ui_cobrand:"Virtuoso"};
	var addthis_share = { url_transforms : { clean: true, remove: ['sid'] } };
    /*]]>*/
    </script>
    <script type="text/javascript">
	var fb_like_id = document.getElementById('fb_like_id');
	if (fb_like_id) fb_like_id.setAttribute('fb:like:layout', 'button_count');
	var g_plusone_id = document.getElementById('g_plusone_id');
	if (g_plusone_id) g_plusone_id.setAttribute('g:plusone:size', 'medium');
    </script>
    <script type="text/javascript" src="http<?V case is_https_ctx () when 1 then 's' else '' end ?>://s7.addthis.com/js/250/addthis_widget.js#pubid=<?=_addthis_key?>"></script>
    <!-- AddThis Button END -->
  </div><!-- ft_s -->
<?vsp } ?>
      <div id="ft_t"><br/>
        Alternative Linked Data Documents:
	<?vsp if (VAD_CHECK_VERSION ('html5pivotviewer') is not null) { ?>	
	<a href="/HtmlPivotViewer/?url=<?vsp http_url (desc_resource_uri); ?>" title="PivotViewer page for exploring results and generating new queries (HTML5)" target="_blank">PivotViewer</a> 
	|
	<?vsp } else if (VAD_CHECK_VERSION ('PivotViewer') is not null) { ?>	
	<a href="/PivotViewer/?url=<?vsp http_url (desc_resource_uri); ?>" title="PivotViewer page for exploring results and generating new queries (Silverlight)" target="_blank">PivotViewer</a> 
	|
	<?vsp } ?>
	<?vsp if (VAD_CHECK_VERSION ('rdf_mappers') is not null) { ?>
	<a href="<?vsp http (rdfdesc_http_url (page_resource_uri)); ?>" target="_blank">Sponger</a>
	|
	<?vsp } ?>
	<?vsp if (VAD_CHECK_VERSION ('iSPARQL') is not null) { ?>
	<a href="/isparql/view/?query=<?vsp http_url (desc_qr); ?>&amp;resultview=browser" title="Interactive Query By Example oriented SPARQL UI" target="_blank">iSPARQL</a>
	|
	<?vsp } ?>
	<a href="http://linkeddata.uriburner.com/ode/?uri=<?vsp http_url (page_resource_uri); ?>" title="Basic navigation and exploration" target="_blank">ODE</a>

        &nbsp; &nbsp; Content Formats: &nbsp; 
	<a href="<?=rdf_link?><?= sprintf ('&output=%U', 'text/cxml')?>"><img src="/fct/images/cxml_doc.png" class="dicon"/></a> 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'text/csv')?>"><img src="/fct/images/csv_doc.png" class="dicon"/></a>  
	&nbsp; &nbsp; RDF &nbsp; 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'text/plain') ?>"><img src="/fct/images/ntriples_doc.png" class="dicon"/></a>
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'text/turtle') ?>"><img src="/fct/images/n3turtle_doc.png" class="dicon"/></a>
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'application/ld+json')?>"><img src="/fct/images/jsonld_doc.png" class="dicon"/></a> 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'application/rdf+json')?>"><img src="/fct/images/json_doc.png" class="dicon"/></a> 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'application/rdf+xml') ?>"><img src="/fct/images/xml_doc.png" class="dicon"/></a>  
	&nbsp; &nbsp; ODATA &nbsp; 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'application/atom+xml')?>"><img src="/fct/images/atom_doc.png" class="dicon"/></a> 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'application/odata+json')?>"><img src="/fct/images/json_doc.png" class="dicon"/></a>
	&nbsp; &nbsp; Microdata &nbsp; 
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'application/microdata+json') ?>"><img src="/fct/images/json_doc.png" class="dicon"/></a>
	<a href="<?=rdf_link?><?=sprintf ('&output=%U', 'text/html') ?>"><img src="/fct/images/html_doc.png" class="dicon"/></a>  
        &nbsp; &nbsp;<a href="/fct/facet_doc.html">About</a>&nbsp; &nbsp;
      </div> <!-- #ft_t -->
      <div id="ft_b">
        <a href="http://linkeddata.org/"><img alt="This material is Open Knowledge" src="/fct/images/LoDLogo.gif" style="border-width:0"/></a> &nbsp;
        <a href="http://dbpedia.org/sparql"><img alt="W3C Semantic Web Technology" src="/fct/images/sw-sparql-blue.png" style="border-width:0"/></a>
        <a href="<?=rdf_link?>" title="RDF data"><img src="/fct/images/sw-rdf-blue.png" alt="[RDF Data]" style="border-width:0"/></a>

	<!--span 
	resource="http://www.w3.org/TR/rdfa-syntax"
	rel="dc:conformsTo" xmlns:dc="http://purl.org/dc/terms/">
	<a href="http://validator.w3.org/check?uri=referer"><img
	    src="http://www.w3.org/Icons/valid-xhtml-rdfa"
	    alt="Valid XHTML + RDFa" height="27" /></a>
	</span-->
	<br />
	<?vsp fct_virt_info (); ?><br />
	<?vsp
          declare license_text varchar;
          license_text := registry_get ('fct_license_text');

          if (license_text) {
            http(license_text);
	  }

        ?>
	Data on this page belongs to its respective rights holders.<br/>
	Virtuoso Faceted Browser Copyright &copy; 2009-<?V "LEFT" (datestring (now ()), 4)?> OpenLink Software 
      </div> <!-- #ft_b -->
    </div> <!-- #FT -->
    </div> <!-- #PG -->
<!--    <div id="fct_selector_tpl" style="display:none">
      <h3></h3>
      <p class="fct_sel_expln"></p>
      <div class="form_row"><label for=""></label><input type="text" class="prop_val_lo"/></div><br/>
      <div class="form_row"><label for=""></label><input type="text" class="prop_val_hi"/></div>
    </div -->
  </body>
</html>
