comparison runner/FeatureExtractionManager.cpp @ 227:88044af67bd1

Better error reporting for transform load (from RDF and XML)
author Chris Cannam
date Thu, 25 Feb 2016 10:53:10 +0000
parents d0fe861bb116
children 9a10c3ffff47
comparison
equal deleted inserted replaced
226:4941e8b167c0 227:88044af67bd1
425 } 425 }
426 return result; 426 return result;
427 } 427 }
428 428
429 bool FeatureExtractionManager::addFeatureExtractorFromFile 429 bool FeatureExtractionManager::addFeatureExtractorFromFile
430 (QString transformXmlFile, const vector<FeatureWriter*> &writers) 430 (QString transformFile, const vector<FeatureWriter*> &writers)
431 { 431 {
432 // We support two formats for transform description files, XML (in
433 // a format specific to Sonic Annotator) and RDF/Turtle. The RDF
434 // format can describe multiple transforms in a single file, the
435 // XML only one.
436
437 // Possible errors we should report:
438 //
439 // 1. File does not exist or cannot be opened
440 // 2. File is ostensibly XML, but is not parseable
441 // 3. File is ostensibly Turtle, but is not parseable
442 // 4. File is XML, but contains no valid transform (e.g. is unrelated XML)
443 // 5. File is Turtle, but contains no valid transform(s)
444 // 6. File is Turtle and contains both valid and invalid transform(s)
445
446 {
447 // We don't actually need to open this here yet, we just hoist
448 // it to the top for error reporting purposes
449 QFile file(transformFile);
450 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
451 // Error case 1. File does not exist or cannot be opened
452 cerr << "ERROR: Failed to open transform file \"" << transformFile
453 << "\" for reading" << endl;
454 return false;
455 }
456 }
457
432 bool tryRdf = true; 458 bool tryRdf = true;
433 459 if (transformFile.endsWith(".xml") || transformFile.endsWith(".XML")) {
434 if (transformXmlFile.endsWith(".xml") || transformXmlFile.endsWith(".XML")) {
435 // We don't support RDF-XML (and nor does the underlying 460 // We don't support RDF-XML (and nor does the underlying
436 // parser library) so skip the RDF parse if the filename 461 // parser library) so skip the RDF parse if the filename
437 // suggests XML, to avoid puking out a load of errors from 462 // suggests XML, to avoid puking out a load of errors from
438 // feeding XML to a Turtle parser 463 // feeding XML to a Turtle parser
439 tryRdf = false; 464 tryRdf = false;
440 } 465 }
441 466
467 bool tryXml = true;
468 if (transformFile.endsWith(".ttl") || transformFile.endsWith(".TTL") ||
469 transformFile.endsWith(".ntriples") || transformFile.endsWith(".NTRIPLES") ||
470 transformFile.endsWith(".n3") || transformFile.endsWith(".N3")) {
471 tryXml = false;
472 }
473
474 QString rdfError, xmlError;
475
442 if (tryRdf) { 476 if (tryRdf) {
477
443 RDFTransformFactory factory 478 RDFTransformFactory factory
444 (QUrl::fromLocalFile(QFileInfo(transformXmlFile).absoluteFilePath()) 479 (QUrl::fromLocalFile(QFileInfo(transformFile).absoluteFilePath())
445 .toString()); 480 .toString());
446 ProgressPrinter printer("Parsing transforms RDF file"); 481 ProgressPrinter printer("Parsing transforms RDF file");
447 std::vector<Transform> transforms = factory.getTransforms(&printer); 482 std::vector<Transform> transforms = factory.getTransforms(&printer);
448 if (!factory.isOK()) { 483
449 cerr << "WARNING: FeatureExtractionManager::addFeatureExtractorFromFile: Failed to parse transforms file: " << factory.getErrorString().toStdString() << endl; 484 if (factory.isOK()) {
485 if (transforms.empty()) {
486 cerr << "ERROR: Transform file \"" << transformFile
487 << "\" is valid RDF but defines no transforms" << endl;
488 return false;
489 } else {
490 bool success = true;
491 for (int i = 0; i < (int)transforms.size(); ++i) {
492 if (!addFeatureExtractor(transforms[i], writers)) {
493 success = false;
494 }
495 }
496 return success;
497 }
498 } else { // !factory.isOK()
450 if (factory.isRDF()) { 499 if (factory.isRDF()) {
451 return false; // no point trying it as XML 500 cerr << "ERROR: Invalid transform RDF file \"" << transformFile
452 } 501 << "\": " << factory.getErrorString() << endl;
453 } 502 return false;
454 if (!transforms.empty()) { 503 }
455 bool success = true; 504
456 for (int i = 0; i < (int)transforms.size(); ++i) { 505 // the not-RDF case: fall through without reporting an
457 if (!addFeatureExtractor(transforms[i], writers)) { 506 // error, so we try the file as XML, and if that fails, we
458 success = false; 507 // print a general unparseable-file error
459 } 508 rdfError = factory.getErrorString();
460 } 509 }
461 return success; 510 }
462 } 511
463 } 512 if (tryXml) {
464 513
465 QFile file(transformXmlFile); 514 QFile file(transformFile);
466 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 515 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
467 cerr << "ERROR: Failed to open transform XML file \"" 516 cerr << "ERROR: Failed to open transform file \""
468 << transformXmlFile.toStdString() << "\" for reading" << endl; 517 << transformFile.toStdString() << "\" for reading" << endl;
469 return false; 518 return false;
470 } 519 }
471 520
472 QTextStream *qts = new QTextStream(&file); 521 QTextStream *qts = new QTextStream(&file);
473 QString qs = qts->readAll(); 522 QString qs = qts->readAll();
474 delete qts; 523 delete qts;
475 file.close(); 524 file.close();
476 525
477 Transform transform(qs); 526 Transform transform(qs);
478 527 xmlError = transform.getErrorString();
479 return addFeatureExtractor(transform, writers); 528
529 if (xmlError == "") {
530
531 if (transform.getIdentifier() == "") {
532 cerr << "ERROR: Transform file \"" << transformFile
533 << "\" is valid XML but defines no transform" << endl;
534 return false;
535 }
536
537 return addFeatureExtractor(transform, writers);
538 }
539 }
540
541 cerr << "ERROR: Transform file \"" << transformFile
542 << "\" could not be parsed" << endl;
543 if (rdfError != "") {
544 cerr << "ERROR: RDF parser reported: " << rdfError << endl;
545 }
546 if (xmlError != "") {
547 cerr << "ERROR: XML parser reported: " << xmlError << endl;
548 }
549
550 return false;
480 } 551 }
481 552
482 void FeatureExtractionManager::addSource(QString audioSource, bool willMultiplex) 553 void FeatureExtractionManager::addSource(QString audioSource, bool willMultiplex)
483 { 554 {
484 std::cerr << "Have audio source: \"" << audioSource.toStdString() << "\"" << std::endl; 555 std::cerr << "Have audio source: \"" << audioSource.toStdString() << "\"" << std::endl;
487 // first audio source and we need it to establish default channel 558 // first audio source and we need it to establish default channel
488 // count and sample rate 559 // count and sample rate
489 560
490 if (m_channels == 0 || m_defaultSampleRate == 0) { 561 if (m_channels == 0 || m_defaultSampleRate == 0) {
491 562
492 ProgressPrinter retrievalProgress("Determining default rate and channel count from first input file..."); 563 ProgressPrinter retrievalProgress("Retrieving first input file to determine default rate and channel count...");
493 564
494 FileSource source(audioSource, &retrievalProgress); 565 FileSource source(audioSource, &retrievalProgress);
495 if (!source.isAvailable()) { 566 if (!source.isAvailable()) {
496 cerr << "ERROR: File or URL \"" << audioSource.toStdString() 567 cerr << "ERROR: File or URL \"" << audioSource.toStdString()
497 << "\" could not be located"; 568 << "\" could not be located";
522 593
523 if (!willMultiplex) { 594 if (!willMultiplex) {
524 if (m_channels == 0) { 595 if (m_channels == 0) {
525 m_channels = reader->getChannelCount(); 596 m_channels = reader->getChannelCount();
526 cerr << "Taking default channel count of " 597 cerr << "Taking default channel count of "
527 << reader->getChannelCount() << " from file" << endl; 598 << reader->getChannelCount() << " from audio file" << endl;
528 } 599 }
529 } 600 }
530 601
531 if (m_defaultSampleRate == 0) { 602 if (m_defaultSampleRate == 0) {
532 m_defaultSampleRate = reader->getNativeRate(); 603 m_defaultSampleRate = reader->getNativeRate();
533 cerr << "Taking default sample rate of " 604 cerr << "Taking default sample rate of "
534 << reader->getNativeRate() << "Hz from file" << endl; 605 << reader->getNativeRate() << "Hz from audio file" << endl;
535 cerr << "(Note: Default may be overridden by transforms)" << endl; 606 cerr << "(Note: Default may be overridden by transforms)" << endl;
536 } 607 }
537 608
538 m_readyReaders[audioSource] = reader; 609 m_readyReaders[audioSource] = reader;
539 } 610 }