Author Topic: Is the GetByName() API function completely robust?  (Read 1776 times)

Colin Coates

  • EA User
  • **
  • Posts: 30
  • Karma: +0/-0
    • View Profile
Is the GetByName() API function completely robust?
« on: June 19, 2018, 07:35:24 pm »
I have written a PHP script that:
1.   Connects to a running instance of Sparx Enterprise Architect
2.   Opens a CSV file (PHP functionality)
3.   Reads each row of the CSV file
4.   Creates requirement elements depending on the contents of each row
 
Before creating a new requirement element, the script looks for whether a requirement with the same name (id) already exists.
 
The script contains a log message:
echo ($view->Elements->GetByName($id))->Name . "\r\n";
 
On executing the script, I see the many error messages like:
PHP Notice:  Trying to get property 'Name' of non-object in D:\colin.coates\php\visualize-requirements.php on line 43
 
It looks like something is wrong with the creation of new requirement elements in my script:
Code: [Select]
function new_rqmnt($view, $id, $text) : object {
    $rqmnt = null;
    if ($view != null) {
        $rqmnt = $view->Elements->AddNew($id, "SysML1.4::Requirement");
        $rqmnt->Update();
        $taggedValues = $rqmnt->TaggedValues;
        foreach ($taggedValues as $taggedValue) {
            switch ($taggedValue->Name) {
            case "id":
                $taggedValue->Value = $id;
                break;
            case "text":
                // $taggedValue->Value = "<memo>";
                $taggedValue->Notes = $text;
                break;
            default:
                echo "Tag \"$taggedValue-Name\" not found!\r\n";
            }
            $taggedValue->Update();
        }
        $rqmnt->Update();
        echo ($view->Elements->GetByName($id))->Name . "\r\n";
        return $rqmnt;
    } else {
        echo "Null view object?\r\n";
        return null;
    }
}

I am using Sparx Enterprise Architect version 13.5.1352 and PHP version 7.2.1.

Can you suggest what the problem might be?

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 10524
  • Karma: +358/-31
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Is the GetByName() API function completely robust?
« Reply #1 on: June 19, 2018, 07:58:46 pm »
Colin,

I see two problems

1. You are not refreshing the Elements collection, so the elements you are adding are not found in the .Elements collection. This is the one time you should call Refresh()
2. You are using GetByName(). I don't trust that operation :-\. On half of the EA.Collections it won't work and will throw an error. And if it does work I'm not sure in which order I will get something, and if it is case sensitive or not.  Anyway, I always write my own operation iterating over the objects in the EA.Collection.

Alternatives to using GetByName():
- in case it is a smallish collection then just iterate over the collection and test for the name yourself
- If the EA.Collection is rather large, and you will need most of them in some way then you can iterate over the collection and put them into a Dictionary with the name as key.
- If the EA.Collection is rather large, and you only need a few of them then you will be better off using Repository.GetElementSet() passing an SQL query as parameter.

Geert

Colin Coates

  • EA User
  • **
  • Posts: 30
  • Karma: +0/-0
    • View Profile
Re: Is the GetByName() API function completely robust?
« Reply #2 on: June 19, 2018, 08:26:38 pm »
Hi Geert, thanks for your expert suggestions!

I will try making the modifications you suggest and will (hopefully) be able get back to you with a confirmation of success. :)

Colin Coates

  • EA User
  • **
  • Posts: 30
  • Karma: +0/-0
    • View Profile
Re: Is the GetByName() API function completely robust?
« Reply #3 on: June 23, 2018, 03:59:38 am »
I can confirm that all your suggestions were excellent Geert!  8)

I have included my PHP script in the hopes it might be of some assistance to others.
Code: [Select]
<?php

$arqmnts 
= array();
$acnnctrs = array();

function 
get_ids(string $cell) : array {
    
$ids = array();
    if (
$cell != "") {
        
$tail $cell;
        
$names = array();
        do {
            
$pos strpos($tail"\n");
            if (
$pos === false) {
                
$ids[] = $tail;
            } else {
                
$ids[] = substr($tail0$pos-1);
                
$tail substr($tail$pos+1); 
            }
        } while (
$pos);
    }
    return 
$ids;
}

// Create SysML 1.4 Requirement element
function new_rqmnt(object $viewstring $idstring $text) : object {
    if (
$view != null) {
        
$rqmnt $view->Elements->AddNew($id"SysML1.4::Requirement");        
        
$tvs $rqmnt->TaggedValues;
        foreach (
$tvs as $tv) {
            switch (
$tv->Name) {
            case 
"id":
                
$tv->Value $id;
                break;
            case 
"text":
                
$tv->Notes $text;
                break;
            default:
                echo 
"Tag \"$tv->Name\" not found!\r\n";
            }
            
$tv->Update(); 
        }
        
$rqmnt->Update();
        
$rqmnt->Refresh();
        return 
$rqmnt;
    } else {
        echo 
"Null view object?\r\n";
        return 
null;
    }
}

function 
dependency(string $sourcestring $target) {
    global 
$acnnctrs$arqmnts;

    if (
array_key_exists($source$acnnctrs) &&
        
array_key_exists($target$acnnctrs[$source])) {
        return; 
// relationship already exists
    
} else {
        
$cs $arqmnts[$source]->Connectors;
        
$c $cs->AddNew("""SysML1.4::Trace");
        
$c->SupplierID $arqmnts[$target]->ElementID;
        
$c->Update();
        
$cs->Refresh();
        
$acnnctrs[$source][$target] = $c// Might be useful in future
    
}
}


function 
get_requirement(object $viewstring $idstring $text) : object {
    global 
$arqmnts;

    if (
array_key_exists($id$arqmnts)) {
        return 
$arqmnts[$id];
    } else {
        return 
$arqmnts[$id] = new_rqmnt($view$id$text);
    }
}

function 
trim_whitespace(array $row) : array {
        
$row[0] = trim($row[0]);
        
$row[1] = trim($row[1]);
        
$row[2] = trim($row[2]);
        
$row[3] = trim($row[3]);
        
$row[4] = trim($row[4]);
        
$row[5] = trim($row[5]);
        return 
$row;
}

function 
import_rqrmnts(object $view) {
    
$filename "WSR Requirement Decomposition for EA.csv"// "csv/wsr-no-hypens.csv";
    
$file fopen($filename'r');
    while ((
$row fgetcsv($file)) != false) {
        echo 
".";
        
$row trim_whitespace($row);
        
$wsr_id $row[0];
        
$wsr_text $row[1];
        
$cdr_ids get_IDs($row[2]);
        
$cdr_text $row[3];
        
$tes_ids get_IDs($row[4]);
        
$tes_text $row[5];
        
        if (
$wsr_id != "WSR Requirement ID") { // ignore header row
            
$wsr get_requirement($view$wsr_id$wsr_text);

            foreach (
$cdr_ids as $cdr_id) {
                
$cdr get_requirement($view$cdr_id$cdr_text);
                
dependency($cdr_id$wsr_id);
                foreach (
$tes_ids as $tes_id) {
                    
$tes get_requirement($view$tes_id$tes_text);
                    
dependency($tes_id$wsr_id);
                }
            }
        
            if (
count($cdr_ids) == 0) {
                foreach (
$tes_ids as $tes_id) {
                    
$tes get_requirement($view$tes_id$tes_text);
                    
dependency($tes_id$wsr_id);
                }
            }
        }
    }
    
fclose($file);
}

// Create Requirements view if necessary
function check_requirements_view(object $packages) : object {
    foreach (
$packages as $package) {
        if (
$package->Name == 'Requirements') {
            return 
$package;
        }
    }
    
$obj $packages->AddNew("Requirements" "Package");
    
$obj->Update();
    return 
$obj;
}

function 
main() {
    
$app com_get_active_object("EA.App");

    echo 
"Connected...\r\n";

    foreach (
$app->Repository->Models as $model) {
        if (
$model->name == "temporary") {
            
$requirements check_requirements_view($model->Packages);
            
import_rqrmnts($requirements);
        }
    }
    
$app null;
}

main();

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 10524
  • Karma: +358/-31
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Is the GetByName() API function completely robust?
« Reply #4 on: June 25, 2018, 10:50:01 pm »
Cool, thanks for the feedback Colin.

Geert

Arquesoft (Mauricio Moya)

  • EA User
  • **
  • Posts: 264
  • Karma: +5/-3
  • EA Consulting and development in Spanish
    • View Profile
    • Arquesoft website
Re: Is the GetByName() API function completely robust?
« Reply #5 on: June 28, 2018, 07:17:15 am »
Note it is possible to have several elements with the same name.
-------------
Need email notifications in EA? fully-automated baselines? a simple way to share your models via web? A copy of all your model diagrams in a folder? visit https://latam.arquesoft.com/en