/** * Akce pro vytvoření nového atributu * @SWG\Post( * tags={"Attributes"}, * path="/attributes", * summary="Create new attribute using defined preprocessing", * consumes={"application/json","application/xml"}, * produces={"application/json","application/xml"}, * security={{"apiKey":{}},{"apiKeyHeader":{}}}, * @SWG\Parameter( * description="New attribute", * name="body", * required=true, * @SWG\Schema(ref="#/definitions/NewAttributeInput"), * in="body" * ), * @SWG\Response( * response=201, * description="Attribute created", * @SWG\Schema( * ref="#/definitions/AttributeResponse" * ) * ), * @SWG\Response( * response=400, * description="Invalid API key supplied", * @SWG\Schema(ref="#/definitions/StatusResponse") * ) * ) * @throws \InvalidArgumentException */ public function actionCreate() { /** @var array $inputData */ $inputData = $this->input->getData(); $miner = $this->findMinerWithCheckAccess(@$inputData['miner']); $this->minersFacade->checkMinerMetasource($miner); $currentUser = $this->getCurrentUser(); //aktualizace informace o datových sloupcích $this->datasourcesFacade->updateDatasourceColumns($miner->datasource, $currentUser); try { if (!empty($inputData['column'])) { $datasourceColumn = $this->datasourcesFacade->findDatasourceColumn($miner->datasource, @$inputData['column']); } else { $datasourceColumn = $this->datasourcesFacade->findDatasourceColumnByName($miner->datasource, @$inputData['columnName']); } } catch (\Exception $e) { throw new InvalidArgumentException("Datasource columns was not found: " . @$inputData['columnName']); } //inicializace formátu $format = $datasourceColumn->format; if (!$format) { //TODO implementovat podporu automatického mapování $format = $this->metaAttributesFacade->simpleCreateMetaAttributeWithFormatFromDatasourceColumn($datasourceColumn, $currentUser); $datasourceColumn->format = $format; $this->datasourcesFacade->saveDatasourceColumn($datasourceColumn); } //vytvoření nového atributu $attribute = new Attribute(); $attribute->metasource = $miner->metasource; $attribute->datasourceColumn = $datasourceColumn; $attribute->name = $this->minersFacade->prepareNewAttributeName($miner, $inputData['name']); $attribute->type = $attribute->datasourceColumn->type; if (@$inputData['specialPreprocessing'] == Preprocessing::SPECIALTYPE_EACHONE) { $preprocessing = $this->metaAttributesFacade->findPreprocessingEachOne($datasourceColumn->format); $attribute->preprocessing = $preprocessing; } else { throw new \BadMethodCallException('Selected preprocessing type is not supported.'); //FIXME je nutné nalézt příslušný preprocessing... } $attribute->active = false; $this->metasourcesFacade->saveAttribute($attribute); //inicializace preprocessingu $metasourceTask = $this->metasourcesFacade->startAttributesPreprocessing($miner->metasource, [$attribute]); while ($metasourceTask && $metasourceTask->state != MetasourceTask::STATE_DONE) { $metasourceTask = $this->metasourcesFacade->preprocessAttributes($metasourceTask); } //smazání předzpracovávací úlohy $this->metasourcesFacade->deleteMetasourceTask($metasourceTask); $this->setXmlMapperElements('attribute'); $this->resource = $attribute->getDataArr(); $this->sendResource(); }
/** * Funkce vracející formulář pro vytvoření atributu na základě vybraného sloupce a preprocessingu * @return Form */ protected function createComponentNewAttributeForm() { $form = new Form(); $presenter = $this; $form->setTranslator($this->translator); $form->addHidden('miner'); $form->addHidden('column'); $form->addHidden('preprocessing'); $form->addText('attributeName', 'Attribute name:')->setRequired('Input attribute name!')->addRule(Form::PATTERN, 'Attribute name can contain only letters, numbers and _ and has start with a letter.', '[a-zA-Z]{1}\\w*')->addRule(function (TextInput $input) { //kontrola, jestli již existuje atribtu se zadaným názvem $values = $input->getForm(true)->getValues(); $miner = $this->findMinerWithCheckAccess($values->miner); $attributes = $miner->metasource->attributes; if (!empty($attributes)) { foreach ($attributes as $attribute) { if ($attribute->name == $input->value) { return false; } } } return true; }, 'Attribute with this name already exists!'); $form->addSubmit('submit', 'Create attribute')->onClick[] = function (SubmitButton $button) { $values = $button->form->values; $miner = $this->findMinerWithCheckAccess($values->miner); $this->minersFacade->checkMinerMetasource($miner); $attribute = new Attribute(); $attribute->metasource = $miner->metasource; $attribute->datasourceColumn = $this->datasourcesFacade->findDatasourceColumn($miner->datasource, $values->column); $attribute->name = $values->attributeName; $attribute->type = $attribute->datasourceColumn->type; $attribute->preprocessing = $this->metaAttributesFacade->findPreprocessing($values->preprocessing); $attribute->active = false; $this->metasourcesFacade->saveAttribute($attribute); $metasourceTask = $this->metasourcesFacade->startAttributesPreprocessing($miner->metasource, [$attribute]); $this->redirect('preprocessingTask', ['id' => $metasourceTask->metasourceTaskId]); }; $storno = $form->addSubmit('storno', 'storno'); $storno->setValidationScope(array()); $storno->onClick[] = function (SubmitButton $button) use($presenter) { //přesměrování na výběr preprocessingu $values = $button->form->getValues(); $presenter->redirect('addAttribute', array('column' => $values->column, 'miner' => $values->miner)); }; return $form; }
/** * Funkce pro vytvoření metaatributu a formátu na základě hodnot datového sloupce * @param string $metaAttributeName * @param string $formatName * @param DatasourceColumn $datasourceColumn * @param DbColumnValuesStatistic $columnValuesStatistic * @param string $formatType * @param bool $formatShared * @return Format */ private function createMetaAttributeFromDatasourceColumn($metaAttributeName, $formatName, DatasourceColumn $datasourceColumn, DbColumnValuesStatistic $columnValuesStatistic, $formatType, $formatShared = false) { $metaAttribute = $this->metaAttributesFacade->findOrCreateMetaAttributeWithName($metaAttributeName); return $this->metaAttributesFacade->createFormatFromDatasourceColumn($metaAttribute, $formatName, $datasourceColumn, $columnValuesStatistic, $formatType, $formatShared, $this->presenter->getUser()->getId()); }
/** * Funkce pro načtení PMML * @param string|\SimpleXMLElement $pmml * @param int &$rulesCount = null - informace o počtu importovaných pravidel * @param bool $updateImportedRulesHeads=false * @return bool * @throws \Exception */ public function fullParseRulesPMML($pmml, &$rulesCount = null, $updateImportedRulesHeads = false) { Debugger::log('fullParseRulesPMML start ' . time(), ILogger::DEBUG); if ($pmml instanceof \SimpleXMLElement) { $xml = $pmml; } else { $xml = simplexml_load_string($pmml); } $xml->registerXPathNamespace('guha', 'http://keg.vse.cz/ns/GUHA0.1rev1'); $guhaAssociationModel = $xml->xpath('//guha:AssociationModel'); $guhaAssociationModel = $guhaAssociationModel[0]; $rulesCount = (string) $guhaAssociationModel['numberOfRules']; /** @var \SimpleXMLElement $associationRulesXml */ $associationRulesXml = $guhaAssociationModel->AssociationRules; if (count($associationRulesXml->AssociationRule) == 0) { return true; } //pokud nejsou vrácena žádná pravidla, nemá smysl zpracovávat cedenty... #region zpracování cedentů jen s jedním subcedentem $dbaItems = $associationRulesXml->xpath('./DBA[count(./BARef)=1]'); $alternativeCedentIdsArr = array(); if (!empty($dbaItems)) { foreach ($dbaItems as $dbaItem) { $idStr = (string) $dbaItem['id']; $BARefStr = (string) $dbaItem->BARef; $alternativeCedentIdsArr[$idStr] = isset($alternativeCedentIdsArr[$BARefStr]) ? $alternativeCedentIdsArr[$BARefStr] : $BARefStr; } } if (!empty($alternativeCedentIdsArr)) { do { $repeat = false; foreach ($alternativeCedentIdsArr as $id => $referencedId) { if (isset($alternativeCedentIdsArr[$referencedId])) { $alternativeCedentIdsArr[$id] = $alternativeCedentIdsArr[$referencedId]; $repeat = true; } } } while ($repeat); } #endregion /** @var Cedent[] $cedentsArr */ $cedentsArr = []; /** @var RuleAttribute[] $ruleAttributesArr */ $ruleAttributesArr = []; /** @var string[] $unprocessedIdsArr */ $unprocessedIdsArr = []; /** @var ValuesBin[]|Value[] $valuesBinsArr */ $valuesBinsArr = []; /** @var Attribute[] $attributesArr - pole indexované pomocí názvů atributů použitých v PMML */ $attributesArr = $this->miner->metasource->getAttributesByNamesArr(); #region zpracování rule attributes $bbaItems = $associationRulesXml->xpath('//BBA'); if (!empty($bbaItems)) { foreach ($bbaItems as $bbaItem) { $ruleAttribute = new RuleAttribute(); $idStr = (string) $bbaItem['id']; //uložení vazby na Attribute $attributeName = (string) $bbaItem->FieldRef; $valueName = (string) $bbaItem->CatRef; $attribute = $attributesArr[$attributeName]; $ruleAttribute->attribute = $attribute; $valueItem = $attribute->preprocessing->findValue($valueName); if ($valueItem instanceof Value) { $ruleAttribute->value = $valueItem; } elseif ($valueItem instanceof ValuesBin) { $ruleAttribute->valuesBin = $valueItem; } elseif ($attribute->preprocessing->specialType == Preprocessing::SPECIALTYPE_EACHONE) { //pokud jde o preprocessing each-one a nebyla nalezena příslušná hodnota v DB, tak ji uložíme $value = new Value(); $value->format = $attribute->preprocessing->format; $value->value = $valueName; $this->metaAttributesFacade->saveValue($value); $ruleAttribute->value = $value; } $this->rulesFacade->saveRuleAttribute($ruleAttribute); $ruleAttributesArr[$idStr] = $ruleAttribute; } } //pročištění pole s alternativními IDčky if (!empty($alternativeCedentIdsArr)) { foreach ($alternativeCedentIdsArr as $id => $alternativeId) { if (isset($ruleAttributesArr[$alternativeId])) { unset($alternativeCedentIdsArr[$id]); } } } #endregion #region zpracování cedentů s více subcedenty/hodnotami $dbaItems = $associationRulesXml->xpath('./DBA[count(./BARef)>0]'); if (!empty($dbaItems)) { do { foreach ($dbaItems as $dbaItem) { $idStr = (string) $dbaItem['id']; if (isset($cedentsArr[$idStr])) { continue; } if (isset($alternativeCedentIdsArr[$idStr])) { continue; } if (isset($ruleAttributesArr[$idStr])) { continue; } $process = true; foreach ($dbaItem->BARef as $BARef) { $BARefStr = (string) $BARef; if (isset($alternativeCedentIdsArr[$BARefStr])) { $BARefStr = $alternativeCedentIdsArr[$BARefStr]; } if (!isset($cedentsArr[$BARefStr]) && !isset($ruleAttributesArr[$BARefStr])) { $unprocessedIdsArr[$BARefStr] = $BARefStr; $process = false; } } if ($process) { unset($unprocessedIdsArr[$idStr]); //vytvoření konkrétního cedentu... $cedent = new Cedent(); if (isset($dbaItem['connective'])) { $cedent->connective = Strings::lower((string) $dbaItem['connective']); } else { $cedent->connective = 'conjunction'; } $this->rulesFacade->saveCedent($cedent); $cedentsArr[$idStr] = $cedent; foreach ($dbaItem->BARef as $BARef) { $BARefStr = (string) $BARef; if (isset($alternativeCedentIdsArr[$BARefStr])) { $BARefStr = $alternativeCedentIdsArr[$BARefStr]; } if (isset($cedentsArr[$BARefStr])) { $cedent->addToCedents($cedentsArr[$BARefStr]); } elseif (isset($ruleAttributesArr[$BARefStr])) { $cedent->addToRuleAttributes($ruleAttributesArr[$BARefStr]); } } $this->rulesFacade->saveCedent($cedent); } else { $unprocessedIdsArr[$idStr] = $idStr; } } } while (!empty($unprocessedIdsArr)); } #endregion #region association rules /** @var Cedent[] $topCedentsArr - pole s cedenty na vrcholné úrovni (pokud je ruleAttribute přímo na vrcholné úrovni, musí být zabalen v cedentu)*/ $topCedentsArr = array(); foreach ($associationRulesXml->AssociationRule as $associationRule) { $rule = false; if ($updateImportedRulesHeads) { try { $rule = $this->rulesFacade->findRuleByPmmlImportId($this->task->taskId, (string) $associationRule['id']); } catch (\Exception $e) { /*ignore*/ } } if (!$rule) { $rule = new Rule(); } $rule->task = $this->task; #region antecedent if (isset($associationRule['antecedent'])) { //jde o pravidlo s antecedentem $antecedentId = (string) $associationRule['antecedent']; if (isset($alternativeCedentIdsArr[$antecedentId])) { $antecedentId = $alternativeCedentIdsArr[$antecedentId]; } if (isset($cedentsArr[$antecedentId])) { $rule->antecedent = $cedentsArr[$antecedentId]; } else { if (isset($ruleAttributesArr[$antecedentId])) { if (!isset($topCedentsArr[$antecedentId])) { $cedent = new Cedent(); $cedent->connective = 'conjunction'; $this->rulesFacade->saveCedent($cedent); $topCedentsArr[$antecedentId] = $cedent; $cedent->addToRuleAttributes($ruleAttributesArr[$antecedentId]); $this->rulesFacade->saveCedent($cedent); } $rule->antecedent = $topCedentsArr[$antecedentId]; } else { throw new \Exception('Import failed!'); } } } else { //jde o pravidlo bez antecedentu $rule->antecedent = null; } #endregion antecedent #region consequent $consequentId = (string) $associationRule['consequent']; if (isset($alternativeCedentIdsArr[$consequentId])) { $consequentId = $alternativeCedentIdsArr[$consequentId]; } if (isset($cedentsArr[$consequentId])) { $rule->consequent = $cedentsArr[$consequentId]; } else { if (isset($ruleAttributesArr[$consequentId])) { if (!isset($topCedentsArr[$consequentId])) { $cedent = new Cedent(); $cedent->connective = 'conjunction'; $this->rulesFacade->saveCedent($cedent); $topCedentsArr[$consequentId] = $cedent; $cedent->addToRuleAttributes($ruleAttributesArr[$consequentId]); $this->rulesFacade->saveCedent($cedent); } $rule->consequent = $topCedentsArr[$consequentId]; } else { throw new \Exception('Import failed!'); } } #endregion consequent $rule->text = (string) $associationRule->Text; $fourFtTable = $associationRule->FourFtTable; $rule->a = (string) $fourFtTable['a']; $rule->b = (string) $fourFtTable['b']; $rule->c = (string) $fourFtTable['c']; $rule->d = (string) $fourFtTable['d']; $this->rulesFacade->saveRule($rule); } $this->rulesFacade->calculateMissingInterestMeasures($this->task); #endregion association rules Debugger::log('fullParseRulesPMML end ' . time(), ILogger::DEBUG); return true; }