<?php
/**  @class EPNResourcesManager 
*    @version $Id: EPNResourcesManager.php 2183 2014-03-13 14:59:19Z elena $
*    @brief Manager to create EPN resources from AMDA descriptors files
*    
*/

define("EPNRES_IVOID_CDPP","ivo://cdpp");
define("EPNRES_IVOID_IRAP",EPNRES_IVOID_CDPP."/irap");
define("EPNRES_IVOID_AMDA",EPNRES_IVOID_IRAP."/amda");
define("EPNRES_IVOID_DATA",EPNRES_IVOID_AMDA."/dataset");
define("EPNRES_IVOID_INST",EPNRES_IVOID_AMDA."/instrument");
define("EPNRES_IVOID_MIS",EPNRES_IVOID_AMDA."/mission");


define("EPNRES_PUBLISHER","CDPP - Centre de Données de la Physique des Plasma");

define("EPNRES_CONTACT_NAME","CDPP/AMDA Team");
define("EPNRES_CONTACT_ADDRESS","IRAP, 9 avenue du Colonel Roche, 31028 TOULOUSE, CEDEX 4, FRANCE");
define("EPNRES_CONTACT_EMAIL","amda@irap.omp.eu");
define("EPNRES_CONTACT_TELEPHONE","");

define("EPNRES_REFERENCE_URL","http://cdpp-amda.cesr.fr/DDHTML/index.html");

define("EPNRES_INSTRUMENTS_FILE",EPNResources."instruments.xml");
define("EPNRES_TARGETS_FILE",LocalData."targets.xml");


class EPNResourcesManager
{
	 protected $infoMgr;
	 protected $amdaClient;
	 protected $inst_doc;
	 protected $inst_xp;
	 protected $targ_doc;
	 protected $targ_xp;
	
  function __construct($amdaClient)
  {
  	 $this->infoMgr = new ParamsInfoMgr();
  	 $this->amdaClient = $amdaClient;
  }

  private function initInstrumentsFile()
  {
  	 $this->inst_doc = new DOMDocument();
    $this->inst_doc->formatOutput = TRUE;
    
    $node = $this->inst_doc->createElement('Instruments');
			 $this->inst_doc->appendChild($node);
    
			 $this->inst_xp = new DOMXPath($this->inst_doc);
  }
  
  private function loadTargetsFile()
  {
  	 $this->targ_doc = new DOMDocument();
    $this->targ_doc->formatOutput = TRUE;
    
    if (!$this->targ_doc->load(EPNRES_TARGETS_FILE))
    {
    	 printf("[ERROR] Cannot load tagets file %s\n",EPNRES_TARGETS_FILE);
    	 return false;
    }
    
    $this->targ_xp = new DOMXPath($this->targ_doc);
    
    return true;
  }
  
  public function createResources()
  {
  	 $this->initInstrumentsFile();
  	 
  	 if (!$this->loadTargetsFile())
      return false;
      
  	 $this->infoMgr->forEachAllDDDatasets(array($this,'createResource'));
  	 
  	 $this->inst_doc->save(EPNRES_INSTRUMENTS_FILE);
  }
  
  function createResource($infos)
  {
  	 $dataset_id = $infos["dataset"]["id"];
  	 
    $newres_doc = new DOMDocument();
    $newres_doc->formatOutput = TRUE;

    $epn_id = str_replace(":","_",$dataset_id);
    $newres_path = EPNResources."EPNresource_".$epn_id.".xml";

    // create skeleton

    $this->getDataCollection($newres_doc);
    $this->getAccessURL($newres_doc);
    $this->getTitle($newres_doc);
    $this->getShortName($newres_doc);
    $this->getIdentifier($newres_doc);
    $this->getCuration($newres_doc);
      $this->getPublisher($newres_doc);
      $this->getCreator($newres_doc);
        $this->getCreatorName($newres_doc);
        $this->getCreatorLogo($newres_doc);
      $this->getContact($newres_doc);
        $this->getContactName($newres_doc);
        $this->getContactAddress($newres_doc);
        $this->getContactEmail($newres_doc);
        $this->getContactTelephone($newres_doc);
    $this->getContent($newres_doc);
      $this->getSubject($newres_doc);
      $this->getDescription($newres_doc);
      $this->getReferenceURL($newres_doc);
      $this->getContributor($newres_doc);
    $this->getResource($newres_doc);
    $this->getDataset($newres_doc);
      $this->getGeneralMetadata($newres_doc);
        $this->getFormat($newres_doc);
        $this->getRight($newres_doc);
        $this->getCalibration($newres_doc);
        $this->getResourceType($newres_doc);
      $this->getInstrument($newres_doc);
        $this->getFacility($newres_doc);
          $this->getResourceName($newres_doc);
        $this->getInstrumentName($newres_doc);
        $this->getAlternateInstrumentName($newres_doc);
        $this->getInstrumentClass($newres_doc);
        $this->getInstrumentReferenceURL($newres_doc);
          $this->getAnyURI($newres_doc);
      $this->getTargets($newres_doc);
        $this->getTargetType($newres_doc);
          $this->getTargetClass($newres_doc);
    $this->getCoverage($newres_doc);
      $this->getMeasurementType($newres_doc);
      $this->getAstroCoordSystem($newres_doc);
        $this->getTimeFrame($newres_doc);
          $this->getTimeScale($newres_doc);
      $this->getAstroCoordArea($newres_doc);
        $this->getTimeInterval($newres_doc);
          $this->getIntegrationTime($newres_doc);
            $this->getMinIntegrationTime($newres_doc);
            $this->getMaxIntegrationTime($newres_doc);
          $this->getSamplingStep($newres_doc);
            $this->getMinSamplingStep($newres_doc);
            $this->getMaxSamplingStep($newres_doc);
          $this->getStartTime($newres_doc);
            $this->getStartTimeISO($newres_doc);
          $this->getStopTime($newres_doc);
            $this->getStopTimeISO($newres_doc);
        $this->getSpectralInterval($newres_doc);
          $this->getSpectralResolution($newres_doc);
            $this->getSpectralMinResolution($newres_doc);
            $this->getSpectralMaxResolution($newres_doc);
          $this->getSpectralLoLimit($newres_doc);
          $this->getSpectralHiLimit($newres_doc);
          $this->getSpectralSamplingStep($newres_doc);
            $this->getMinSpectralSamplingStep($newres_doc);
            $this->getMaxSpectralSamplingStep($newres_doc);
        $this->getSpectralParticles($newres_doc);
          $this->getParticlesResolution($newres_doc);
            $this->getParticlesMinResolution($newres_doc);
            $this->getParticlesMaxResolution($newres_doc);
          $this->getParticlesLoLimit($newres_doc);
          $this->getParticlesHiLimit($newres_doc);
          $this->getParticlesSamplingStep($newres_doc);
            $this->getMinParticlesSamplingStep($newres_doc);
            $this->getMaxParticlesSamplingStep($newres_doc);
    $this->getTableset($newres_doc);
      $this->getSchema($newres_doc);
        $this->getSchemaColumn($newres_doc);
          $this->getSchemaColumnName($newres_doc);
          $this->getSchemaColumnDescription($newres_doc);
          $this->getSchemaColumnUnit($newres_doc);
          $this->getSchemaColumnUCD($newres_doc);
          $this->getSchemaColumnDataproductType($newres_doc);
          $this->getSchemaColumnDataType($newres_doc);

    // fill
    $date = date("Y-m-d\TH:i:s");

    $this->setDataCollection($newres_doc,$epn_id,$date,$date,"");
    
    $accessURL = EPNTAP_AMDA."?REQUEST=doQuery&amp;LANG=ADQL&amp;QUERY=SELECT * FROM amdadb.epn_core WHERE dataset_id = '".$epn_id."' AND resource_type = 'granule' ORDER BY time_min&amp;FORMAT=votable/td";
    $this->setAccessURL($newres_doc,$accessURL);
    
    $this->setTitle($newres_doc,$infos['dataset']['infos']['title']);
    
    $this->setShortName($newres_doc,$epn_id); 
     
    $this->setIdentifier($newres_doc,EPNRES_IVOID_DATA,$epn_id);
    
    $this->setPublisher($newres_doc,EPNRES_PUBLISHER);
    
    $this->setCreator($newres_doc,$infos['dataset']['infos']['creator'],"");
    
    $this->setContact($newres_doc,EPNRES_IVOID_AMDA,EPNRES_CONTACT_NAME,EPNRES_CONTACT_ADDRESS,EPNRES_CONTACT_EMAIL,EPNRES_CONTACT_TELEPHONE);   
    
    foreach ($infos['dataset']['infos']['subject'] as $s)
      $this->addSubject($newres_doc,$s);
    
    $this->setDescription($newres_doc,$infos['dataset']['infos']['description']);
    
    $this->setReferenceURL($newres_doc,$infos['submission']['infos']['help'],$infos['instrument']['infos']['help'],$infos['dataset']['infos']['help']);
    
    foreach ($infos['dataset']['infos']['contributor'] as $c)
      $this->addContributor($newres_doc,$c);
    
    $this->setCalibration($newres_doc,$infos['dataset']['infos']['calibration']);

    $this->setFormat($newres_doc,"votable");
    
    if (!isset($infos['mission']['infos']['group']) || ($infos['mission']['infos']['group'] == ""))
      $this->setRight($newres_doc,"secure");
    else
      $this->setRight($newres_doc,"proprietary");
    
    $this->setResourceType($newres_doc,"dataset");
    
    $this->setInstrument($newres_doc,$infos['mission']['id'],$infos['submission']['name'],$infos['submission']['infos']['class'],
                         $infos['instrument']['infos']['id'],$infos['instrument']['name'],$infos['instrument']['infos']['alternamename'],
                         $infos['instrument']['infos']['class'],$infos['instrument']['infos']['refURL']);
    
    foreach ($infos['dataset']['infos']['target'] as $t)
      $this->addTarget($newres_doc,$t);

    $this->setMeasurementType($newres_doc,$infos['dataset']['infos']['parameters']);

    $this->setTimeInterval($newres_doc,$dataset_id,$infos['dataset']['infos']['minsampling'],$infos['dataset']['infos']['maxsampling'],
                           $infos['dataset']['infos']['starttime'],$infos['dataset']['infos']['stoptime']);

    foreach ($infos['dataset']['infos']['parameters'] as $param)
      $this->addColumn($newres_doc,$param['name'],$param['description'],$param['units'],$param['ucd'],$param['type'],'float');
                           
    $newres_doc->save($newres_path);
   // printf("[INFO] Create new EPN resource file %s\n",$newres_path);
  }

  function setDataCollection($res_doc,$id,$created,$updated,$status)
  {
    $node = $this->getDataCollection($res_doc);
    $node->setAttribute('id',$id);
    $node->setAttribute('created',$created);
    $node->setAttribute('updated',$updated);
    $node->setAttribute('status',$status);
  }

  function setPublisher($res_doc,$publisher)
  {
    $node = $this->getPublisher($res_doc);
    $node->nodeValue = $publisher;
  }

  function setContact($res_doc,$ivo_id,$name,$address,$email,$telephone)
  {
    $node = $this->getContactName($res_doc);
    $node->setAttribute('ivo-id',$ivo_id);
    $node->nodeValue = $name;
    $node = $this->getContactAddress($res_doc);
    $node->nodeValue = $address;
    $node = $this->getContactEmail($res_doc);
    $node->nodeValue = $email;
    $node = $this->getContactTelephone($res_doc);
    $node->nodeValue = $telephone;
  }

  function setReferenceURL($res_doc,$mission_help,$instrument_help,$dataset_help)
  {
    $node = $this->getReferenceURL($res_doc);
    if (isset($dataset_help) && ($dataset_help != ''))
      $node->nodeValue = $dataset_help;
    else if (isset($instrument_help) && ($instrument_help != ''))
      $node->nodeValue = $instrument_help;
    else if (isset($mission_help) && ($mission_help != ''))
      $node->nodeValue = $mission_help;
    else
      $node->nodeValue = EPNRES_REFERENCE_URL;
  }

  function getRealSampling($sampling)
  {
  	 list($val,$unit) = sscanf($sampling,"%f%s");
    if ($unit == "s")
      $sampling = 1*$sampling;
    else if ($unit == "m")
      $sampling = 60*$sampling;
    else if ($unit == "h")
      $sampling = 3600*$sampling;
    else if ($unit == "Hz")
      $sampling = 1./$sampling;
    else
      printf("[WARNING] EPNResource : Unknown sampling unit %s\n",$unit);
    return $sampling;
  }
  
  function getRealStartStop($name)
  {
  	 return $this->amdaClient->client->getStartStop($name);
	 }
  
  function days2MonthDay($oldDate)
  {
    list($year, $day, $hour, $min, $sec) = sscanf($oldDate, "%04d%03d%02d%02d%02d");
    $newDate = date("Y-m-d\TH:i:s",strtotime("+$day days",strtotime("$year-01-01 $hour:$min:$sec")));
    return $newDate;
  }
  
  function setTimeInterval($res_doc,$dataset_id,$minres,$maxres,$start,$stop)
  {
    $node = $this->getTimeInterval($res_doc);
    $node->setAttribute('ucd','time.epoch');
    $node = $this->getSamplingStep($res_doc);
    if ($minres == $maxres)
      $node->setAttribute('type','constant');
    else
      $node->setAttribute('type','variable');
    $node->setAttribute('unit','secondes');
    $node = $this->getMinSamplingStep($res_doc);
    $node->nodeValue = $this->getRealSampling($minres);
    $node = $this->getMaxSamplingStep($res_doc);
    $node->nodeValue = $this->getRealSampling($maxres);
    
    $startstop = $this->getRealStartStop($dataset_id);
    $Time = explode("-",$startstop);
    
    $node = $this->getStartTimeISO($res_doc);
    $node->nodeValue = $this->days2MonthDay($Time[0]);
    $node  = $this->getStopTimeISO($res_doc);
    $node->nodeValue = $this->days2MonthDay($Time[1]);
    $node = $this->getTimeScale($res_doc);
    $node->nodeValue = 'UTC';
  }

  function setAccessURL($res_doc,$access_url)
  {
    $node = $this->getAccessURL($res_doc);
    $node->nodeValue = $access_url;
  }

  function setTitle($res_doc,$title)
  {
    $node = $this->getTitle($res_doc);
    $node->nodeValue = $title;
  }

  function setShortName($res_doc,$shortName)
  {
    $node = $this->getShortName($res_doc);
    $node->nodeValue = $shortName;
  }

  function setIdentifier($res_doc,$ivo_id,$dataset_id)
  {
    $node = $this->getIdentifier($res_doc);
    $node->nodeValue = $ivo_id."/".$dataset_id;
  }

  function setCreator($res_doc,$name,$logo)
  {
    $node = $this->getCreatorName($res_doc);
    $node->nodeValue = $name;

    $node = $this->getCreatorLogo($res_doc);
    $node->nodeValue = $logo;
  }

  function setCalibration($res_doc,$cal)
  {
    $node = $this->getCalibration($res_doc);
    $node->nodeValue = $cal;
  }

  function setResourceType($res_doc,$type)
  {
    $node = $this->getResourceType($res_doc);
    $node->nodeValue = $type;
  }

  function setInstrument($res_doc,$mis_id,$submis_name,$mis_class,$inst_id,$inst_name,$inst_altname,$inst_class,$inst_refurl)
  {
    $node = $this->getInstrument($res_doc);

    $node->setAttribute('id',$inst_id);
    
    $node = $this->getFacility($res_doc);
    $node->setAttribute('ivo-id',EPNRES_IVOID_MIS."/".$submis_name);
    $node->setAttribute('class',$mis_class);

    $node = $this->getResourceName($res_doc);
    $node->nodeValue = $mis_id;

    $node = $this->getInstrumentName($res_doc);
    $node->setAttribute('ivo-id',EPNRES_IVOID_INST."/".$inst_id);
    $node->nodeValue = $inst_name;

    foreach ($inst_altname as $a)
      $this->addInstAltName($res_doc,$a);
      
    foreach ($inst_class as $c)
      $this->addInstClass($res_doc,$c);

    $node = $this->getInstrumentReferenceURL($res_doc);
    $node->setAttribute('use','full');

    $node = $this->getAnyURI($res_doc);
    $node->nodeValue = $inst_refurl;
    
    $instnode = $this->inst_xp->query("//Instruments/instrument[@id='".$inst_id."']");
    if ($instnode->length < 1)
    {
    	 $instnode = $this->inst_doc->importNode($this->getInstrument($res_doc),true);
    	 $this->inst_doc->documentElement->appendChild($instnode);
    }
  }

  function setMeasurementType($res_doc,$params)
  {
    $node = $this->getMeasurementType($res_doc);
    
    $ucds = array();
    foreach ($params as $param)
    {
    	 $param_ucds = explode($param['ucd'],";");
    	 foreach ($param_ucds as $param_ucd)
    	 {
    	   if ($param_ucd == 'ToDo')
    	     continue;
        $toadd = true;
    	   foreach ($ucds as $ucd)
    	     if ($ucd == $param_ucd)
    	     {
    	   	   $toadd = false;
    	   	   break;
    	     }
    	   if ($toadd)
    	     array_push($ucds,$param['ucd']);
    	 }
    }
    
    $ucd_str = "";
    foreach ($ucds as $ucd)
    {
    	 if ($ucd_str != "")
    	   $ucd_str .= ";";
    	 $ucd_str .= $ucd;
    }
    
    $node->nodeValue = $ucd_str;
  }

  function setFormat($res_doc,$format)
  {
    $node = $this->getFormat($res_doc);
    $node->nodeValue = $format;
  }

  function setRight($res_doc,$right)
  {
    $node = $this->getRight($res_doc);
    $node->nodeValue = $right;
  }

  function setDescription($res_doc,$description)
  {
    $node = $this->getDescription($res_doc);
    $node->nodeValue .= $description;
  }

  function addTarget($res_doc,$target_id)
  {
  	 //find target in targets file
  	 $tar_info = $this->targ_xp->query("//Targets/TargetType[@id='".$target_id."']");
  	 if ($tar_info->length < 1)
  	 {
  	 	 printf("[WARNING] Cannot find target info %s\n",$target_id);
  	 	 return;
  	 }
  	 $tar_info = $tar_info->item(0);
  	
  	 //add target in epn resource
  	 $targets = $this->getTargets($res_doc);
  	 
  	 $targetnodes = $targets->getElementsByTagName("TargetType");
    foreach ($targetnodes as $targetnode)
      if ($targetnode->getAttribute("id") == $target_id)
        return;
    
    foreach ($targetnodes as $targetnode)
       if ($targetnode->getAttribute("id") == '')
         $targets->removeChild($targetnode);
       
    $node = $res_doc->importNode($tar_info,true);
    $targets->appendChild($node);
  }
  
  function addColumn($res_doc,$param_name,$param_des,$param_unit,$param_ucd,$param_datatype,$param_prodtype)
  {
    $schema = $this->getSchema($res_doc);

    $columns = $schema->getElementsByTagName("column");
    foreach ($columns as $column)
    {
      $names = $column->getElementsByTagName("name");
      if ($names->length < 1)
        continue;
      if (($names->item(0)->nodeValue == $param_name) || ($names->item(0)->nodeValue == ''))
      {
        $param_column = $column;
        break;
      }
    }
    if (!isset($param_column))
    {
      //create new column
      $param_column = $this->addToNode($res_doc,$schema,'column');
      $this->addToNode($res_doc,$param_column,'name');
      $this->addToNode($res_doc,$param_column,'description');
      $this->addToNode($res_doc,$param_column,'unit');
      $this->addToNode($res_doc,$param_column,'ucd');
      $this->addToNode($res_doc,$param_column,'dataproduct_type');
      $this->addToNode($res_doc,$param_column,'dataType');
    }
    //set param info
    $node = $this->getFromNode($res_doc,$param_column,'name');
    $node->nodeValue = $param_name;
    $node = $this->getFromNode($res_doc,$param_column,'description');
    $node->nodeValue = $param_des;
    $node = $this->getFromNode($res_doc,$param_column,'unit');
    $node->nodeValue = $param_unit;
    $node = $this->getFromNode($res_doc,$param_column,'ucd');
    $node->nodeValue = $param_ucd;
    $node = $this->getFromNode($res_doc,$param_column,'dataproduct_type');
    $node->nodeValue = $param_datatype;
    $node = $this->getFromNode($res_doc,$param_column,'dataType');
    $node->nodeValue = $param_prodtype;
  }

  function addSubject($res_doc,$subject)
  {
  	 $content = $this->getContent($res_doc);

    $subjects = $content->getElementsByTagName("subject");
    foreach($subjects as $s)
      if ($s->nodeValue == $subject)
        return;

    foreach($subjects as $s)
      if ($s->nodeValue == '')
      {
        $s->nodeValue = $subject;
        return;
      }

    $s = $this->addToNode($res_doc,$content,'subject');
    $s->nodeValue = $subject;
  }
  
  function addContributor($res_doc,$contributor)
  {
  	 $content = $this->getContent($res_doc);

    $contributors = $content->getElementsByTagName("contributor");
    foreach($contributors as $c)
      if ($c->nodeValue == $contributor)
        return;

    foreach($contributors as $c)
      if ($c->nodeValue == '')
      {
        $c->nodeValue = $contributor;
        return;
      }

    $c = $this->addToNode($res_doc,$content,'contributor');
    $c->nodeValue = $contributor;
  }
  
  function addInstAltName($res_doc,$altName)
  {
  	 $content = $this->getInstrument($res_doc);

    $altnames = $content->getElementsByTagName("alternateInstrumentName");
    foreach($altnames as $a)
      if ($a->nodeValue == $altName)
        return;

    foreach($altnames as $a)
      if ($a->nodeValue == '')
      {
        $a->nodeValue = $altName;
        return;
      }

    $a = $this->addToNode($res_doc,$content,'alternateInstrumentName');
    $a->nodeValue = $altName;
  }
  
  function addInstClass($res_doc,$class)
  {
  	 $content = $this->getInstrument($res_doc);

    $classes = $content->getElementsByTagName("instrumentClass");
    foreach($classes as $c)
      if ($c->nodeValue == $class)
        return;

    foreach($classes as $c)
      if ($c->nodeValue == '')
      {
        $c->nodeValue = $class;
        return;
      }

    $c = $this->addToNode($res_doc,$content,'instrumentClass');
    $c->nodeValue = $class;
  }
  
  function addToNode($res_doc,$node,$tagname)
  {
    $newnode = $res_doc->createElement($tagname);
    $node->appendChild($newnode);
    return $newnode;    
  }

  function getFromNode($res_doc,$node,$tagname)
  {
    $nodes = $node->getElementsByTagName($tagname);
    if ($nodes->length == 0)
      return $this->addToNode($res_doc,$node,$tagname);
    return $nodes->item(0);
  }

  function getDataCollection($res_doc)
  {
    return $this->getFromNode($res_doc,$res_doc,'DataCollection');
  }

  function getAccessURL($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'accessURL');
  }

  function getTitle($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'title');
  }

  function getShortName($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'shortName');
  }

  function getIdentifier($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'Identifier');
  }

  function getCuration($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'curation');
  }

  function getPublisher($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCuration($res_doc),'publisher');
  }

  function getCreator($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCuration($res_doc),'creator');
  }

  function getCreatorName($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCreator($res_doc),'name');
  }

  function getCreatorLogo($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCreator($res_doc),'logo');
  }

  function getContact($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCuration($res_doc),'contact');
  }

  function getContactName($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContact($res_doc),'name');
  }

  function getContactAddress($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContact($res_doc),'address');
  }

  function getContactEmail($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContact($res_doc),'email');
  }

  function getContactTelephone($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContact($res_doc),'telephone');
  }

  function getContent($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'content');
  }

  function getSubject($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContent($res_doc),'subject');
  }

  function getDescription($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContent($res_doc),'description');
  } 

  function getReferenceURL($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContent($res_doc),'referenceURL');
  }

  function getContributor($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getContent($res_doc),'contributor');
  }

  function getResource($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'resource');
  }

  function getDataset($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getResource($res_doc),'dataset');
  }

  function getGeneralMetadata($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataset($res_doc),'generalMetadata');
  }

  function getFormat($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getGeneralMetadata($res_doc),'format');
  }

  function getRight($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getGeneralMetadata($res_doc),'right');
  }

  function getResourceType($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getGeneralMetadata($res_doc),'resource_type');
  }

  function getCalibration($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getGeneralMetadata($res_doc),'calibration');
  }

  function getInstrument($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataset($res_doc),'instrument');
  }

  function getFacility($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,(isset($inst) ? $inst : $this->getInstrument($res_doc)),'facility');
  }

  function getResourceName($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,$this->getFacility($res_doc,$inst),'ResourceName');
  }

  function getInstrumentName($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,(isset($inst) ? $inst : $this->getInstrument($res_doc)),'InstrumentName');
  }

  function getAlternateInstrumentName($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,(isset($inst) ? $inst : $this->getInstrument($res_doc)),'alternateInstrumentName');
  }

  function getInstrumentClass($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,(isset($inst) ? $inst : $this->getInstrument($res_doc)),'instrumentClass');
  }

  function getInstrumentReferenceURL($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,(isset($inst) ? $inst : $this->getInstrument($res_doc)),'referenceURL');
  }

  function getAnyURI($res_doc,$inst)
  {
    return $this->getFromNode($res_doc,$this->getInstrumentReferenceURL($res_doc,$inst),'anyURI');
  }

  function getTargets($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataset($res_doc),'targets');
  }

  function getTargetType($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTargets($res_doc),'TargetType');
  }

  function getTargetClass($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTargetType($res_doc),'targetClass');
  }

  function getCoverage($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'coverage');
  }

  function getMeasurementType($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCoverage($res_doc),'measurementType');
  }

  function getAstroCoordSystem($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCoverage($res_doc),'AstroCoordSystem');
  }

  function getTimeFrame($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getAstroCoordSystem($res_doc),'TimeFrame');
  }

  function getTimeScale($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTimeFrame($res_doc),'TimeScale');
  }

  function getAstroCoordArea($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getCoverage($res_doc),'AstroCoordArea');
  }

  function getTimeInterval($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getAstroCoordArea($res_doc),'TimeInterval');
  }

  function getIntegrationTime($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTimeInterval($res_doc),'resolution');
  }

  function getMinIntegrationTime($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getIntegrationTime($res_doc),'minResolution');
  }

  function getMaxIntegrationTime($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getIntegrationTime($res_doc),'maxResolution');
  }

  function getSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTimeInterval($res_doc),'SamplingStep');
  }

  function getMinSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSamplingStep($res_doc),'minSamplingStep');
  }

  function getMaxSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSamplingStep($res_doc),'maxSamplingStep');
  }

  function getStartTime($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTimeInterval($res_doc),'StartTime');
  }

  function getStartTimeISO($res_doc)
  { 
    return $this->getFromNode($res_doc,$this->getStartTime($res_doc),'ISOTime');
  }

  function getStopTime($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTimeInterval($res_doc),'StopTime');
  }

  function getStopTimeISO($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getStopTime($res_doc),'ISOTime');
  }

  function getSpectralInterval($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getAstroCoordArea($res_doc),'SpectralInterval');
  }

  function getSpectralResolution($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralInterval($res_doc),'resolution');
  }

  function getSpectralMinResolution($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralResolution($res_doc),'minResolution');
  }

  function getSpectralMaxResolution($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralResolution($res_doc),'maxResolution');
  }

  function getSpectralLoLimit($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralInterval($res_doc),'LoLimit');
  }

  function getSpectralHiLimit($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralInterval($res_doc),'HiLimit');
  }

  function getSpectralSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralInterval($res_doc),'SamplingStep');
  }
  
  function getMinSpectralSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralSamplingStep($res_doc),'minSamplingStep');
  }
   
  function getMaxSpectralSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralSamplingStep($res_doc),'maxSamplingStep');
  }

  function getSpectralParticles($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getAstroCoordArea($res_doc),'SpectralParticles');
  }

  function getParticlesResolution($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralParticles($res_doc),'resolution');
  }

  function getParticlesMinResolution($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getParticlesResolution($res_doc),'minResolution');
  }

  function getParticlesMaxResolution($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getParticlesResolution($res_doc),'maxResolution');
  }

  function getParticlesLoLimit($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralParticles($res_doc),'LoLimit');
  }

  function getParticlesHiLimit($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralParticles($res_doc),'HiLimit');
  }

  function getParticlesSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSpectralParticles($res_doc),'SamplingStep');
  }
  
  function getMinParticlesSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getParticlesSamplingStep($res_doc),'minSamplingStep');
  }
   
  function getMaxParticlesSamplingStep($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getParticlesSamplingStep($res_doc),'maxSamplingStep');
  }

  function getTableset($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getDataCollection($res_doc),'tableset');
  }

  function getSchema($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getTableset($res_doc),'schema');
  }

  function getSchemaColumn($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchema($res_doc),'column');
  }

  function getSchemaColumnName($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchemaColumn($res_doc),'name');
  }

  function getSchemaColumnDescription($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchemaColumn($res_doc),'description');
  }

  function getSchemaColumnUnit($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchemaColumn($res_doc),'unit');
  }

  function getSchemaColumnUCD($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchemaColumn($res_doc),'ucd');
  }

  function getSchemaColumnDataType($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchemaColumn($res_doc),'dataType');
  }

  function getSchemaColumnDataproductType($res_doc)
  {
    return $this->getFromNode($res_doc,$this->getSchemaColumn($res_doc),'dataproduct_type');
  }
}
?>