<?PHP

/* RDFInt.php - RDF Interfaces for PHP
 * Copyright 2011 netlabs.org
 * Author: Christian Langanke, Adrian Gschwend
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// load library setup
if (!defined( 'RDFINT')) 
  define( 'RDFINT', getenv( 'PHP_LIBROOT_RDFINT'));
require_once( RDFINT.'/rdfa.php');

class RDFTestCasesManifest {

  private $rdfDataManifest;
  private $exceptions;

  // --------------------------------------------------------

  public function __construct() {

    $remoteManifest = 'http://www.w3.org/2000/10/rdf-tests/rdfcore/Manifest.rdf';

    $aNamespace = array( 'rdf'      => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
                         'test'     => 'http://www.w3.org/2000/10/rdf-tests/rdfcore/testSchema#',
                         'case'     => 'http://www.w3.org/2000/10/rdf-tests/rdfcore/');


    // determine location of local cache file for manifest
    $tmpdir = getenv('tmp');
    if ($tmpdir == '')
      $tmpdir = '/tmp';
    $localManifest = $tmpdir.'/RDFTestcases_Manifest.rdf';

    // cache manifest file first
    if (!file_exists( $localManifest)) {
      $data = file_get_contents( $remoteManifest);
      file_put_contents( $localManifest, $data );
    }

    // load RDF data
    $this->rdfDataManifest = new \rdfa\Data();
    foreach ( $aNamespace as $prefix => $uriNamespace) {
      $this->rdfDataManifest->setMapping( $prefix, $uriNamespace);
    }
    $result = $this->rdfDataManifest->parse( $localManifest);

    // load exception list
    $this->exceptions = explode( "\r\n", file_get_contents( 'exception.lst'));

  } // public function __construct

  // --------------------------------------------------------

  private function _caseNameFromSubject( $uriTestcase) {
    $nameParts = explode( ':', $uriTestcase);
    $name = str_replace( 'Manifest.rdf#', '', $nameParts[1]);
    return $name;

  } // private function _caseNameFromSubject

  // --------------------------------------------------------

  // helper: get projections on approved testcases
  private function _searchApprovedTestcases( $category) {

    // determine data
    $templateTestcase = array( 'input'      => 'test:inputDocument',
                               'output'     => 'test:outputDocument',
                               'conclusion' => 'test:conclusionDocument');

    // assemble query and search
    $query[ 'test:status'] = 'APPROVED';
    $query[ 'rdf:type']    = "test:$category";
    $testcases = $this->rdfDataManifest->query( $query, $templateTestcase);

    // create name attribute from URI
    // unshring URI values
    foreach ($testcases as $testcase) {
      $testcase->name = $this->_caseNameFromSubject( $testcase->getSubject());

      if (isset( $testcase->input))
        $testcase->input = $this->rdfDataManifest->_resolve( $testcase->input);

      if (isset( $testcase->output))
        $testcase->output = $this->rdfDataManifest->_resolve( $testcase->output);

      if (isset( $testcase->conclusion))
        $testcase->conclusion = $this->rdfDataManifest->_resolve( $testcase->conclusion);
    }

    return $testcases;

  } // private function _searchApprovedTestcases

  // --------------------------------------------------------

  // helper: determine names or count of approved testcases for category
  // NOTE: for better performance we use getSubjects() instead of query(),
  //       and check for approval in a further step

  // helper: get subjects of approved testcases
  private function _getApprovedTestcaseSubjects( $category) {

    $uriTestcases = $this->rdfDataManifest->getSubjects( 'rdf:type', "test:$category");
    $count = 0;
    $testcases = array();
    foreach ( $uriTestcases as $uriTestcase) {

      // don't execute if in exception list
      if (array_search( $this->_caseNameFromSubject( $uriTestcase), $this->exceptions) !== false)
        continue;


      if ($this->rdfDataManifest->_getFirstValue( $uriTestcase, 'test:status') == 'APPROVED')
        $testcases[] = $uriTestcase;
    }

    return $testcases;

  } // private function _getApprovedTestcaseSubjects


  private function _countApprovedTestcases( $category) {

    return count( $this->_getApprovedTestcaseSubjects( $category));

  } // private function _countApprovedTestcases

  // --------------------------------------------------------

  public function getParserTests( $category) {

    return $this->_searchApprovedTestcases( $category);

  } // public function getParserTests

  // --------------------------------------------------------

  public function getCategories() {

    // all categories - for later use
    $validTpes = array( 'PositiveParserTest',
                        'NegativeParserTest',
                        'PositiveEntailmentTest',
                        'NegativeEntailmentTest',
                        'MiscellaneousTest');

    $validTpes = array( 'PositiveParserTest');

    return $validTpes;

  } // public function getCategories

  // --------------------------------------------------------

  public function listCases( $category = Null, $verbose = false) {

    // use all categories by default
    if (($category == Null) || ($category == ''))
      $categories = $this->getCategories();
    else
      $categories = array( $category);

    // now list cases
    foreach ($categories as $category) {
      if ($verbose) {
        echo "  $category\n";
        $uriTestcases = $this->_getApprovedTestcaseSubjects( $category);
        $count = count( $uriTestcases);
        foreach ($uriTestcases as $uriTestcase) {
          echo "    " . $this->_caseNameFromSubject( $uriTestcase) . "\n";
        }
      echo "$count cases for: $category\n\n";
      } else {
        $count = $this->_countApprovedTestcases( $category);
        echo "   $category     $count cases\n";
      }
    }

  } // public function listCases

} // class UnitTest


