FOSSology  4.7.1
Open Source License Compliance by Open Source Software
DeciderAgent.php
Go to the documentation of this file.
1 <?php
2 /*
3  Author: Daniele Fognini
4  SPDX-FileCopyrightText: © 2014-2019 Siemens AG
5  SPDX-FileCopyrightText: © 2021 Orange by Piotr Pszczola <piotr.pszczola@orange.com>
6  SPDX-FileCopyrightText: © 2021 Kaushlendra Pratap <kaushlendrapratap.9837@gmail.com>
7  SPDX-FileCopyrightText: © Fossology contributors
8 
9  SPDX-License-Identifier: GPL-2.0-only
10 */
50 namespace Fossology\Decider;
51 
71 use Symfony\Component\Process\Process;
72 
73 include_once(__DIR__ . "/version.php");
74 
79 class DeciderAgent extends Agent
80 {
81  const RULES_NOMOS_IN_MONK = 0x1;
82  const RULES_NOMOS_MONK_NINKA = 0x2;
83  const RULES_BULK_REUSE = 0x4;
84  const RULES_WIP_SCANNER_UPDATES = 0x8;
85  const RULES_OJO_NO_CONTRADICTION = 0x10;
86  const RULES_COPYRIGHT_FALSE_POSITIVE = 0x20;
87  const RULES_COPYRIGHT_FALSE_POSITIVE_CLUTTER = 0x40;
88  const RULES_LICENSE_TYPE_CONCLUSION = 0x80;
89  const RULES_KOTOBA_NO_CONTRADICTION = 0x100;
90  const RULES_RESO_NO_CONTRADICTION = 0x200;
91  const RULES_ALL = self::RULES_NOMOS_IN_MONK | self::RULES_NOMOS_MONK_NINKA |
92  self::RULES_BULK_REUSE | self::RULES_WIP_SCANNER_UPDATES |
93  self::RULES_OJO_NO_CONTRADICTION | self::RULES_RESO_NO_CONTRADICTION |
94  self::RULES_LICENSE_TYPE_CONCLUSION | self::RULES_KOTOBA_NO_CONTRADICTION;
95 
99  private $activeRules;
103  private $licenseType;
107  private $uploadDao;
119  private $clearingDao;
123  private $highlightDao;
127  private $showJobsDao;
131  private $decisionTypes;
135  private $licenseMap = null;
139  private $licenseMapUsage = null;
140 
144  private $copyrightDao;
145 
150 
154  private $licenseDao;
155 
156  function __construct($licenseMapUsage=null)
157  {
158  parent::__construct(AGENT_DECIDER_NAME, AGENT_DECIDER_VERSION, AGENT_DECIDER_REV);
159 
160  $this->uploadDao = $this->container->get('dao.upload');
161  $this->clearingDao = $this->container->get('dao.clearing');
162  $this->highlightDao = $this->container->get('dao.highlight');
163  $this->showJobsDao = $this->container->get('dao.show_jobs');
164  $this->decisionTypes = $this->container->get('decision.types');
165  $this->clearingDecisionProcessor = $this->container->get('businessrules.clearing_decision_processor');
166  $this->agentLicenseEventProcessor = $this->container->get('businessrules.agent_license_event_processor');
167  $this->copyrightDao = $this->container->get('dao.copyright');
168  $this->compatibilityDao = $this->container->get('dao.compatibility');
169  $this->licenseDao = $this->container->get('dao.license');
170  $this->licenseMapUsage = $licenseMapUsage;
171  $this->agentSpecifOptions = "r:t:";
172  }
173 
178  function processUploadId($uploadId)
179  {
180  $args = $this->args;
181  $this->activeRules = array_key_exists('r', $args) ? intval($args['r']) : self::RULES_ALL;
182  $this->licenseType = array_key_exists('t', $args) ?
183  $this->getLicenseType(str_replace(["'", '"'], "", $args['t'])) : "";
184  $this->licenseMap = new LicenseMap($this->dbManager, $this->groupId, $this->licenseMapUsage);
185 
186  if (array_key_exists("r", $args) && (($this->activeRules&self::RULES_COPYRIGHT_FALSE_POSITIVE)== self::RULES_COPYRIGHT_FALSE_POSITIVE)) {
187  $this->getCopyrightsToDisableFalsePositivesClutter($uploadId, false);
188  }
189  if (array_key_exists("r", $args) && (($this->activeRules&self::RULES_COPYRIGHT_FALSE_POSITIVE_CLUTTER)== self::RULES_COPYRIGHT_FALSE_POSITIVE_CLUTTER)) {
190  $this->getCopyrightsToDisableFalsePositivesClutter($uploadId, true);
191  }
192  if (array_key_exists("r", $args) && (($this->activeRules&self::RULES_BULK_REUSE)== self::RULES_BULK_REUSE)) {
193  $bulkReuser = new BulkReuser();
194  $bulkIds = $this->clearingDao->getPreviousBulkIds($uploadId, $this->groupId, $this->userId);
195  if (count($bulkIds) == 0) {
196  return true;
197  }
198  $jqId=0;
199  $minTime="4";
200  $maxTime="60";
201  foreach ($bulkIds as $bulkId) {
202  $jqId = $bulkReuser->rerunBulkAndDeciderOnUpload($uploadId, $this->groupId, $this->userId, $bulkId, $jqId);
203  $this->heartbeat(1);
204  if (!empty($jqId)) {
205  $jqIdRow = $this->showJobsDao->getDataForASingleJob($jqId);
206  while ($this->showJobsDao->getJobStatus($jqId)) {
207  $this->heartbeat(0);
208  $timeInSec = $this->showJobsDao->getEstimatedTime($jqIdRow['jq_job_fk'],'',0,0,1);
209  if ($timeInSec > $maxTime) {
210  sleep($maxTime);
211  } else if ($timeInSec < $minTime) {
212  sleep($minTime);
213  } else {
214  sleep($timeInSec);
215  }
216  }
217  }
218  }
219  }
220  $parentBounds = $this->uploadDao->getParentItemBounds($uploadId);
221  foreach ($this->uploadDao->getContainedItems($parentBounds) as $item) {
222  $process = $this->processItem($item);
223  $this->heartbeat($process);
224  }
225  return true;
226  }
227 
237  private function processItem(Item $item)
238  {
239  $itemTreeBounds = $item->getItemTreeBounds();
240 
241  $unMappedMatches = $this->agentLicenseEventProcessor->getLatestScannerDetectedMatches($itemTreeBounds);
242  $projectedScannerMatches = $this->remapByProjectedId($unMappedMatches);
243 
244  $lastDecision = $this->clearingDao->getRelevantClearingDecision($itemTreeBounds, $this->groupId);
245 
246  if (null!==$lastDecision && $lastDecision->getType()==DecisionTypes::IRRELEVANT) {
247  return 0;
248  }
249 
250  $currentEvents = $this->clearingDao->getRelevantClearingEvents($itemTreeBounds, $this->groupId);
251 
252  $markAsWip = false;
253  if (null !== $lastDecision && $projectedScannerMatches
254  && ($this->activeRules & self::RULES_WIP_SCANNER_UPDATES) == self::RULES_WIP_SCANNER_UPDATES) {
255  $licensesFromDecision = array();
256  foreach ($lastDecision->getClearingLicenses() as $clearingLicense) {
257  $licenseIdFromEvent = $this->licenseMap->getProjectedId($clearingLicense->getLicenseId());
258  $licensesFromDecision[$licenseIdFromEvent] = $licenseIdFromEvent;
259  }
260  $markAsWip = $this->existsUnhandledMatch($projectedScannerMatches,$licensesFromDecision);
261  }
262 
263  if (null !== $lastDecision && $markAsWip) {
264  $this->clearingDao->markDecisionAsWip($item->getId(), $this->userId, $this->groupId);
265  return 1;
266  }
267 
268  /* Kotoba stores findings as clearing events, which would trip the guard
269  below. Auto-conclude here when all events are from kotoba and no scanner
270  license is unaccounted for. */
271  if (null === $lastDecision && count($currentEvents) > 0
272  && ($this->activeRules & self::RULES_KOTOBA_NO_CONTRADICTION) == self::RULES_KOTOBA_NO_CONTRADICTION) {
273  if ($this->autodecideIfKotobaMatchesNoContradiction($itemTreeBounds, $projectedScannerMatches, $currentEvents)) {
274  return 1;
275  }
276  }
277 
278  if (null!==$lastDecision || 0<count($currentEvents)) {
279  return 0;
280  }
281 
282  $haveDecided = false;
283 
284  if (!$haveDecided && ($this->activeRules&self::RULES_OJO_NO_CONTRADICTION) == self::RULES_OJO_NO_CONTRADICTION) {
285  $haveDecided = $this->autodecideIfOjoMatchesNoContradiction($itemTreeBounds, $projectedScannerMatches);
286  }
287 
288  if (!$haveDecided && ($this->activeRules&self::RULES_RESO_NO_CONTRADICTION) == self::RULES_RESO_NO_CONTRADICTION) {
289  $haveDecided = $this->autodecideIfResoMatchesNoContradiction($itemTreeBounds, $projectedScannerMatches);
290  }
291 
292  if (!$haveDecided && ($this->activeRules&self::RULES_NOMOS_IN_MONK) == self::RULES_NOMOS_IN_MONK) {
293  $haveDecided = $this->autodecideNomosMatchesInsideMonk($itemTreeBounds, $projectedScannerMatches);
294  }
295 
296  if (!$haveDecided && ($this->activeRules&self::RULES_NOMOS_MONK_NINKA)== self::RULES_NOMOS_MONK_NINKA) {
297  $haveDecided = $this->autodecideNomosMonkNinka($itemTreeBounds, $projectedScannerMatches);
298  }
299 
300  if (!$haveDecided && ($this->activeRules &
301  self::RULES_LICENSE_TYPE_CONCLUSION) ==
302  self::RULES_LICENSE_TYPE_CONCLUSION) {
303  $haveDecided = $this->autodecideLicenseType($itemTreeBounds,
304  $projectedScannerMatches);
305  }
306 
307  if (!$haveDecided && $markAsWip) {
308  $this->clearingDao->markDecisionAsWip($item->getId(), $this->userId, $this->groupId);
309  }
310 
311  return ($haveDecided||$markAsWip ? 1 : 0);
312  }
313 
320  private function existsUnhandledMatch($projectedScannerMatches, $licensesFromDecision)
321  {
322  foreach (array_keys($projectedScannerMatches) as $projectedLicenseId) {
323  if (!array_key_exists($projectedLicenseId, $licensesFromDecision)) {
324  return true;
325  }
326  }
327  return false;
328  }
329 
338  private function autodecideIfOjoMatchesNoContradiction(ItemTreeBounds $itemTreeBounds, $matches)
339  {
340  $licenseMatchExists = count($matches) > 0;
341  foreach ($matches as $licenseMatches) {
342  $licenseMatchExists = $licenseMatchExists && $this->areOtherScannerFindingsAndOJOAgreed($licenseMatches);
343  }
344 
345  if ($licenseMatchExists) {
346  try {
347  $this->clearingDecisionProcessor->makeDecisionFromLastEvents(
348  $itemTreeBounds, $this->userId, $this->groupId,
349  DecisionTypes::IDENTIFIED, false);
350  } catch (\Exception $e) {
351  echo "Can not auto decide as file '" .
352  $itemTreeBounds->getItemId() . "' contains candidate license.\n";
353  }
354  }
355  return $licenseMatchExists;
356  }
357 
368  private function autodecideIfKotobaMatchesNoContradiction(ItemTreeBounds $itemTreeBounds, $projectedScannerMatches, $currentEvents)
369  {
370  $accountedLicenses = array();
371  foreach ($currentEvents as $event) {
372  if ($event->getEventType() != ClearingEventTypes::KOTOBA) {
373  return false; // human event present; do not override
374  }
375  $projectedId = $this->licenseMap->getProjectedId($event->getLicenseId());
376  $accountedLicenses[$projectedId] = true;
377  }
378 
379  foreach (array_keys($projectedScannerMatches) as $projectedLicenseId) {
380  if (!array_key_exists($projectedLicenseId, $accountedLicenses)) {
381  return false; // unaccounted scanner license: contradiction
382  }
383  }
384 
385  try {
386  $this->clearingDecisionProcessor->makeDecisionFromLastEvents(
387  $itemTreeBounds, $this->userId, $this->groupId,
388  DecisionTypes::IDENTIFIED, false);
389  } catch (\Exception $e) {
390  echo "Can not auto decide as file '" .
391  $itemTreeBounds->getItemId() . "' contains candidate license.\n";
392  return false;
393  }
394  return true;
395  }
396 
405  private function autodecideIfResoMatchesNoContradiction(ItemTreeBounds $itemTreeBounds, $matches)
406  {
407  $licenseMatchExists = count($matches) > 0;
408  foreach ($matches as $licenseMatches) {
409  $licenseMatchExists = $licenseMatchExists && $this->areOtherScannerFindingsAndRESOAgreed($licenseMatches);
410  }
411 
412  if ($licenseMatchExists) {
413  try {
414  $this->clearingDecisionProcessor->makeDecisionFromLastEvents(
415  $itemTreeBounds, $this->userId, $this->groupId,
416  DecisionTypes::IDENTIFIED, false);
417  } catch (\Exception $e) {
418  echo "Can not auto decide as file '" .
419  $itemTreeBounds->getItemId() . "' contains candidate license.\n";
420  }
421  }
422  return $licenseMatchExists;
423  }
424 
433  private function autodecideNomosMonkNinka(ItemTreeBounds $itemTreeBounds, $matches)
434  {
435  $canDecide = (count($matches)>0);
436 
437  foreach ($matches as $licenseMatches) {
438  if (!$canDecide) { // &= is not lazy
439  break;
440  }
441  $canDecide &= $this->areNomosMonkNinkaAgreed($licenseMatches);
442  }
443 
444  if ($canDecide) {
445  $this->clearingDecisionProcessor->makeDecisionFromLastEvents($itemTreeBounds, $this->userId, $this->groupId, DecisionTypes::IDENTIFIED, $global=true);
446  }
447  return $canDecide;
448  }
449 
458  private function autodecideNomosMatchesInsideMonk(ItemTreeBounds $itemTreeBounds, $matches)
459  {
460  $canDecide = (count($matches)>0);
461 
462  foreach ($matches as $licenseMatches) {
463  if (!$canDecide) { // &= is not lazy
464  break;
465  }
466  $canDecide &= $this->areNomosMatchesInsideAMonkMatch($licenseMatches);
467  }
468 
469  if ($canDecide) {
470  $this->clearingDecisionProcessor->makeDecisionFromLastEvents($itemTreeBounds, $this->userId, $this->groupId, DecisionTypes::IDENTIFIED, $global=true);
471  }
472  return $canDecide;
473  }
474 
484  private function autodecideLicenseType(ItemTreeBounds $itemTreeBounds,
485  $matches)
486  {
487  $canDecide = $this->noLicenseConflict($itemTreeBounds, $matches);
488  if ($canDecide) {
489  $canDecide &= $this->allLicenseInType($matches);
490  }
491 
492  if ($canDecide) {
493  $this->clearingDecisionProcessor
494  ->makeDecisionFromLastEvents($itemTreeBounds, $this->userId,
495  $this->groupId, DecisionTypes::IDENTIFIED, DecisionScopes::ITEM, [], true);
496  }
497  return $canDecide;
498  }
499 
506  protected function remapByProjectedId($matches)
507  {
508  $remapped = array();
509  foreach ($matches as $licenseId => $licenseMatches) {
510  $projectedId = $this->licenseMap->getProjectedId($licenseId);
511 
512  foreach ($licenseMatches as $agent => $agentMatches) {
513  $haveId = array_key_exists($projectedId, $remapped);
514  $haveAgent = $haveId && array_key_exists($agent, $remapped[$projectedId]);
515  if ($haveAgent) {
516  $remapped[$projectedId][$agent] = array_merge($remapped[$projectedId][$agent], $agentMatches);
517  } else {
518  $remapped[$projectedId][$agent] = $agentMatches;
519  }
520  }
521  }
522  return $remapped;
523  }
524 
531  private function isRegionIncluded($small, $big)
532  {
533  return ($big[0] >= 0) && ($small[0] >= $big[0]) && ($small[1] <= $big[1]);
534  }
535 
541  private function areNomosMatchesInsideAMonkMatch($licenseMatches)
542  {
543  if (!array_key_exists("nomos", $licenseMatches)) {
544  return false;
545  }
546  if (!array_key_exists("monk", $licenseMatches)) {
547  return false;
548  }
549 
550  foreach ($licenseMatches["nomos"] as $licenseMatch) {
551  $matchId = $licenseMatch->getLicenseFileId();
552  $nomosRegion = $this->highlightDao->getHighlightRegion($matchId);
553 
554  $found = false;
555  foreach ($licenseMatches["monk"] as $monkLicenseMatch) {
556  $monkRegion = $this->highlightDao->getHighlightRegion($monkLicenseMatch->getLicenseFileId());
557  if ($this->isRegionIncluded($nomosRegion, $monkRegion)) {
558  $found = true;
559  break;
560  }
561  }
562  if (!$found) {
563  return false;
564  }
565  }
566 
567  return true;
568  }
569 
575  protected function areNomosMonkNinkaAgreed($licenseMatches)
576  {
577  $scanners = array('nomos','monk','ninka');
578  $vote = array();
579  foreach ($scanners as $scanner) {
580  if (!array_key_exists($scanner, $licenseMatches)) {
581  return false;
582  }
583  foreach ($licenseMatches[$scanner] as $licenseMatch) {
584  $licId = $licenseMatch->getLicenseId();
585  $vote[$licId][$scanner] = true;
586  }
587  }
588 
589  foreach ($vote as $licId=>$voters) {
590  if (count($voters) != 3) {
591  return false;
592  }
593  }
594  return true;
595  }
596 
603  protected function getLicenseIdsOfMatchesForScanner($scanner, $licenseMatches)
604  {
605  if (array_key_exists($scanner, $licenseMatches) === true) {
606  return array_map(
607  function ($match) {
608  return $match->getLicenseId();
609  }, $licenseMatches[$scanner]);
610  }
611  return [];
612  }
613 
619  protected function areOtherScannerFindingsAndOJOAgreed($licenseMatches)
620  {
621  $findingsByOjo = $this->getLicenseIdsOfMatchesForScanner('ojo', $licenseMatches);
622  if (count($findingsByOjo) == 0) {
623  // nothing to do
624  return false;
625  }
626 
627  $findingsByOtherScanner = $this->getLicenseIdsOfMatchesForScanner('nomos', $licenseMatches);
628  if (count($findingsByOtherScanner) == 0) {
629  // nothing found by other scanner, so no contradiction
630  return true;
631  }
632  foreach ($findingsByOtherScanner as $findingsByScanner) {
633  if (in_array($findingsByScanner, $findingsByOjo) === false) {
634  // contradiction found
635  return false;
636  }
637  }
638  return true;
639  }
640 
646  protected function areOtherScannerFindingsAndRESOAgreed($licenseMatches)
647  {
648  $findingsByReso = $this->getLicenseIdsOfMatchesForScanner('reso', $licenseMatches);
649  if (count($findingsByReso) == 0) {
650  // nothing to do
651  return false;
652  }
653 
654  $findingsByOtherScanner = $this->getLicenseIdsOfMatchesForScanner('nomos', $licenseMatches);
655  if (count($findingsByOtherScanner) == 0) {
656  // nothing found by other scanner, so no contradiction
657  return true;
658  }
659  foreach ($findingsByOtherScanner as $findingsByScanner) {
660  if (in_array($findingsByScanner, $findingsByReso) === false) {
661  // contradiction found
662  return false;
663  }
664  }
665  return true;
666  }
667 
675  $clutter_flag): void
676  {
677  if (empty($uploadId)) {
678  return;
679  }
680  $agentName = 'copyright';
681  $uploadTreeTableName = $this->uploadDao->getUploadtreeTableName($uploadId);
682  $scanJobProxy = new ScanJobProxy($GLOBALS['container']->get('dao.agent'), $uploadId);
683  $scanJobProxy->createAgentStatus(array($agentName));
684  $selectedScanners = $scanJobProxy->getLatestSuccessfulAgentIds();
685  if (!array_key_exists($agentName, $selectedScanners)) {
686  return;
687  }
688  $latestXpAgentId = $selectedScanners[$agentName];
689  $extrawhere = ' agent_fk='.$latestXpAgentId;
690  $allCopyrights = $this->copyrightDao->getScannerEntries('copyright',
691  $uploadTreeTableName, $uploadId, null, $extrawhere);
692 
693  if (empty($allCopyrights)) {
694  echo "No copyrights found for upload $uploadId. Skipping false positive deactivation.\n";
695  return;
696  }
697 
698  $copyrightJSON = json_encode($allCopyrights);
699  $tmpFile = tmpfile();
700  $tmpFilePath = stream_get_meta_data($tmpFile)['uri'];
701  fwrite($tmpFile, $copyrightJSON);
702  $deactivatedCopyrightData = $this->callCopyrightDeactivationClutterRemovalScript($tmpFilePath, $clutter_flag);
703  if (empty($deactivatedCopyrightData)) {
704  fclose($tmpFile);
705  return;
706  }
707  $deactivatedCopyrights = json_decode($deactivatedCopyrightData, true);
708  foreach ($deactivatedCopyrights as $deactivatedCopyright) {
709  $item = $deactivatedCopyright['uploadtree_pk'];
710  $itemTreeBounds = $this->uploadDao->getItemTreeBounds($item, $uploadTreeTableName);
711  $hash = $deactivatedCopyright['hash'];
712  $content = $deactivatedCopyright['content'];
713  $cpTable = 'copyright';
714  if ($deactivatedCopyright['is_copyright'] == "t") {
715  $action = '';
716  if (array_key_exists('decluttered_content', $deactivatedCopyright) &&
717  !empty($deactivatedCopyright['decluttered_content'])) {
718  $content = $deactivatedCopyright['decluttered_content'];
719  } else {
720  // No text update. Nothing to do.
721  $this->heartbeat(1);
722  continue;
723  }
724  } else {
725  $action = 'delete';
726  }
727  $this->copyrightDao->updateTable($itemTreeBounds, $hash, $content, $this->userId, $cpTable, $action);
728  $this->heartbeat(1);
729  }
730  fclose($tmpFile);
731  }
732 
739  private function callCopyrightDeactivationClutterRemovalScript($tmpFilePath,
740  $clutter_flag): string
741  {
742  $script = "copyrightDeactivationClutterRemovalScript.py";
743  $args = ["python3", __DIR__ . "/$script", "--file", $tmpFilePath];
744  if ($clutter_flag) {
745  $args[] = "--clutter";
746  }
747 
748  $sleepTime = 5;
749  $maxSleepTime = 25;
750 
751  $process = new Process($args);
752  $process->setTimeout(null); // Remove timeout to run indefinitely.
753  $process->setEnv(set_python_path());
754  $process->start();
755 
756  do {
757  $this->heartbeat(0);
758  sleep($sleepTime);
759  if ($sleepTime < $maxSleepTime) {
760  $sleepTime += 5;
761  }
762  } while ($process->isRunning());
763 
764  echo $process->getErrorOutput();
765 
766  return $process->getOutput();
767  }
768 
774  private function getLicenseType($licenseType)
775  {
776  global $SysConf;
777  $licenseTypes = array_map('trim', explode(',',
778  $SysConf['SYSCONFIG']['LicenseTypes']));
779  if (in_array($licenseType, $licenseTypes)) {
780  return $licenseType;
781  }
782  return "";
783  }
784 
792  protected function noLicenseConflict($itemTreeBounds, $licenseMatches)
793  {
794  $shortnames = [];
795  foreach ($licenseMatches as $agentMatch) {
796  foreach ($agentMatch as $agentLicenseMatches) {
797  foreach ($agentLicenseMatches as $licenseMatch) {
798  $shortnames[$licenseMatch->getLicenseId()] = $licenseMatch
799  ->getLicenseRef()->getShortName();
800  }
801  }
802  }
803  foreach ($shortnames as $shortname) {
804  try {
805  if (! $this->compatibilityDao->getCompatibilityForFile($itemTreeBounds,
806  $shortname)) {
807  return false;
808  }
809  } catch (InvalidAgentStageException $_) {
810  return false;
811  }
812  }
813  return true;
814  }
815 
821  protected function allLicenseInType($licenseMatches)
822  {
823  $licenseTypes = [];
824  foreach ($licenseMatches as $agentMatch) {
825  foreach ($agentMatch as $agentLicenseMatches) {
826  foreach ($agentLicenseMatches as $licenseMatch) {
827  if (!array_key_exists($licenseMatch->getLicenseId(), $licenseTypes)) {
828  $licenseTypes[$licenseMatch->getLicenseId()] = $this->licenseDao
829  ->getLicenseType($licenseMatch->getLicenseId());
830  }
831  }
832  }
833  }
834  if (! in_array($this->licenseType, $licenseTypes)) {
835  return false;
836  }
837  if (! empty(array_diff($licenseTypes, [$this->licenseType]))) {
838  return false;
839  }
840  return true;
841  }
842 }
Prepares bulk licenses for an upload and run DeciderJob on it.
Definition: BulkReuser.php:23
Agent to decide license findings in an upload.
existsUnhandledMatch($projectedScannerMatches, $licensesFromDecision)
Check if matches contains unhandled match.
areOtherScannerFindingsAndRESOAgreed($licenseMatches)
Check if the finding by only contains one single license and that no other scanner (nomos) has produc...
autodecideIfResoMatchesNoContradiction(ItemTreeBounds $itemTreeBounds, $matches)
Auto decide matches which are in nomos, monk, OJO and Reso findings.
processItem(Item $item)
Given an item, check with the $activeRules and apply rules to it.
areOtherScannerFindingsAndOJOAgreed($licenseMatches)
Check if the finding by only contains one single license and that no other scanner (nomos) has produc...
callCopyrightDeactivationClutterRemovalScript($tmpFilePath, $clutter_flag)
autodecideNomosMatchesInsideMonk(ItemTreeBounds $itemTreeBounds, $matches)
Auto decide matches by nomos which are in monk findings.
noLicenseConflict($itemTreeBounds, $licenseMatches)
Check if findings by all agents are same or not.
autodecideNomosMonkNinka(ItemTreeBounds $itemTreeBounds, $matches)
Auto decide matches which are in nomos, monk and ninka findings.
processUploadId($uploadId)
Given an upload ID, process the items in it.
allLicenseInType($licenseMatches)
Check if findings by all agents are same or not.
autodecideLicenseType(ItemTreeBounds $itemTreeBounds, $matches)
Auto decide matches where there is no license conflict.
getLicenseIdsOfMatchesForScanner($scanner, $licenseMatches)
extracts the matches corresponding to a scanner from a $licenseMatches structure
isRegionIncluded($small, $big)
Check if the small highlight region is inside big one.
autodecideIfOjoMatchesNoContradiction(ItemTreeBounds $itemTreeBounds, $matches)
Auto decide matches which are in nomos, monk and OJO findings.
areNomosMatchesInsideAMonkMatch($licenseMatches)
Check if matches by nomos are inside monk findings.
getCopyrightsToDisableFalsePositivesClutter($uploadId, $clutter_flag)
remapByProjectedId($matches)
Given a set of matches, remap according to project id instead of license id.
areNomosMonkNinkaAgreed($licenseMatches)
Check if findings by all agents are same or not.
autodecideIfKotobaMatchesNoContradiction(ItemTreeBounds $itemTreeBounds, $projectedScannerMatches, $currentEvents)
Auto-conclude when kotoba events cover all scanner findings.
Structure of an Agent with all required parameters.
Definition: Agent.php:41
heartbeat($newProcessed)
Send hear beat to the scheduler.
Definition: Agent.php:203
Utility functions to process ClearingDecision.
Wrapper class for license map.
Definition: LicenseMap.php:19
set_python_path()
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
Namespace for decider agent.
Definition: BulkReuser.php:8
$GLOBALS['xyyzzzDeciderJob']