Select to view content in your preferred language

Deleting and creating a containment association within calculate attribute rule

230
2
Jump to solution
3 weeks ago
StijnSchouten
Emerging Contributor

ArcGIS Pro 3.4.4
utility network: 6

Hi utility network peers,

I'm currently a bit stuck developing an attribute rule that when a certain field changes from X to Y it should automatically delete the containment association from X and create the containment association to Y. 

The manual process of deleting the containment association and adding the new containment association works fine within the 'modify association' screen. However, when executing the attribute rule it complains that there is no valid utility network rule. Which is weird as it works manually.

34: Feature or object in unsupported containment relationship.

Anyway here is the arcade expression that is triggered. Is there something wrong here?

var association_table = 'UN_5_ASSOCIATIONS';

function find_parent_matches(parent_sapid) {
    var feature_set = FeatureSetByName($datastore, 'StructureBoundary', ['globalid', 'sapid'], false);
    var sap_related_features = Filter(feature_set, `sapid = '${parent_sapid}'`);
    return sap_related_features;
}

function find_and_delete_existing_associations() {
    var deletes = [];
    var all_associations = FeatureSetByAssociation($feature, 'container');
    var associated_filtered = Filter(all_associations, "className = 'StructureBoundary'");
    if (Count(associated_filtered) == 0) {
        console(`id: ${$feature.objectid} - No existing associations found`);
        return null;
    }
    console(`id: ${$feature.objectid} - station equipment has ${Count(associated_filtered)} existing associations. Deleting...`);
    for (var as in associated_filtered) {
        Push(deletes, {'objectid': as.objectid});
    }
    return {'className': association_table, 'deletes': deletes};
}

function associate_stations(stations) {
    var updates = [];
    for (var station in stations) {
        Push(updates, {'globalID': station.globalid, 'associationType': 'container'});
    }
    if (!IsEmpty(updates)) {
        return {'className': 'StructureBoundary', 'updates': updates};
    }
    return null;
}


function main() {
    var payload = [];

    if ($originalfeature.parent_sapid == $feature.parent_sapid) {
        console(`id: ${$feature.objectid} - station equipment no change detected in parent_sapid ${$feature.parent_sapid}`);
        return;
    }

    console(`id: ${$feature.objectid} - station equipment change detected in parent_sapid ${$originalfeature.parent_sapid} changed to ${$feature.parent_sapid}`);

    var existing_associations = find_and_delete_existing_associations();
    if (!IsEmpty(existing_associations)) {
        Push(payload, existing_associations);
    }

    var matching_stations = find_parent_matches($feature.parent_sapid);
    
    if (Count(matching_stations) == 0) { 
        console(`id: ${$feature.objectid} - Updated station equipment with parent ${$feature.parent_sapid} does not have any related stations`);
        return; 
    }
    console(`id: ${$feature.objectid} - Updated station equipment with parent ${$feature.parent_sapid} has ${Count(matching_stations)} related station, connecting ...`)
    var associated_stations = associate_stations(matching_stations);
    if (!IsEmpty(associated_stations)) {
        Push(payload, associated_stations);
    }
    
    console(payload);

    return {'edit': payload};
}



// Process starts here
if (IndexOf([1,2,3,9,15,16,17,18,19,7], $feature.assetgroup) == -1) {
    return;
}
main()

This is an example from the logs
<Event time="Tue Aug 12 17:57:55.782" type="Debug" thread="679c: Main CIM worker thread" elapsed="0" function="Geodatabase.AttributeRule" code="ArcadeConsole">
[{"className":"UN_5_ASSOCIATIONS","deletes":[{"objectid":317893}]},{"className":"StructureBoundary","updates":[{"associationType":"container","globalID":"{6FF562E2-EB17-4A58-8B8C-DA9718BF9938}"}]}]
</Event>
<Event time="Tue Aug 12 17:57:55.780" type="Debug" thread="679c: Main CIM worker thread" elapsed="0" function="Geodatabase.AttributeRule" code="ArcadeConsole">
id: 266843 - Updated station equipment with parent <redacted> has 1 related station, connecting ...
</Event>
<Event time="Tue Aug 12 17:57:55.777" type="Debug" thread="679c: Main CIM worker thread" elapsed="0" function="Geodatabase.AttributeRule" code="ArcadeConsole">
id: 266843 - station equipment has 1 existing associations. Deleting...
</Event>
<Event time="Tue Aug 12 17:57:55.750" type="Debug" thread="679c: Main CIM worker thread" elapsed="0" function="Geodatabase.AttributeRule" code="ArcadeConsole">
id: 266843 - station equipment change detected in parent_sapid <redacted> changed to <redacted>
</Event>

1 Solution

Accepted Solutions
HusseinNasser2
Esri Contributor

I would recommend not writing to the association table directly as it can be error prune. Instead use the provided attribute rules dictionary APIs 

I authored a blog about it 

https://www.esri.com/arcgis-blog/products/utility-network/electric-gas/advanced-attribute-rules-crea...

 

for more advanced cases use this keyword 

Read more here about "^UN_Association"

https://pro.arcgis.com/en/pro-app/latest/help/data/geodatabases/overview/attribute-rule-dictionary-k...

 

 

 

 

View solution in original post

2 Replies
HusseinNasser2
Esri Contributor

I would recommend not writing to the association table directly as it can be error prune. Instead use the provided attribute rules dictionary APIs 

I authored a blog about it 

https://www.esri.com/arcgis-blog/products/utility-network/electric-gas/advanced-attribute-rules-crea...

 

for more advanced cases use this keyword 

Read more here about "^UN_Association"

https://pro.arcgis.com/en/pro-app/latest/help/data/geodatabases/overview/attribute-rule-dictionary-k...

 

 

 

 

StijnSchouten
Emerging Contributor

Thanks Hussein! 

I've made some adjustments and now it works much better

var association_table = '^UN_Association';

function find_parent_matches(parent_sapid) {
    var feature_set = FeatureSetByName($datastore, 'StructureBoundary', ['globalid', 'sapid'], false);
    var sap_related_features = Filter(feature_set, `sapid = '${parent_sapid}'`);
    return sap_related_features;
}

function find_and_delete_existing_associations() {
    var deletes = [];
    var all_associations = FeatureSetByAssociation($feature, 'container');
    var associated_filtered = Filter(all_associations, "className = 'StructureBoundary'");
    if (Count(associated_filtered) == 0) {
        console(`id: ${$feature.objectid} - No existing associations found`);
        return null;
    }
    console(`id: ${$feature.objectid} - station equipment has ${Count(associated_filtered)} existing associations. Deleting...`);
    for (var as in associated_filtered) {
        Push(deletes, {'objectid': as.objectid});
    }
    return {'className': association_table, 'deletes': deletes};
}

function associate_stations(stations) {
    var updates = [];
    for (var station in stations) {
        Push(updates, {'globalID': station.globalid, 'associationType': 'container'});
    }
    if (Count(updates) > 0) {
        return {'className': 'StructureBoundary', 'updates': updates};
    }
    return null;
}


function main() {
    var payload = [];

    if ($originalfeature.parent_sapid == $feature.parent_sapid) {
        console(`id: ${$feature.objectid} - station equipment no change detected in parent_sapid ${$feature.parent_sapid}`);
        return;
    }

    console(`id: ${$feature.objectid} - station equipment change detected in parent_sapid ${$originalfeature.parent_sapid} changed to ${$feature.parent_sapid}`);

    var existing_associations = find_and_delete_existing_associations();
    if (!IsEmpty(existing_associations)) {
        Push(payload, existing_associations);
    }

    var matching_stations = find_parent_matches($feature.parent_sapid);
    
    if (Count(matching_stations) == 0) { 
        console(`id: ${$feature.objectid} - Updated station equipment with parent ${$feature.parent_sapid} does not have any related stations`);
    } else {
        console(`id: ${$feature.objectid} - Updated station equipment with parent ${$feature.parent_sapid} has ${Count(matching_stations)} related station, connecting ...`);
    }
    var associated_stations = associate_stations(matching_stations);
    if (!IsEmpty(associated_stations)) {
        Push(payload, associated_stations);
    }
    if (Count(payload) > 0) {
        Insert(payload, 0, {'className': 'DHCJunctionObject', 'updates': [{'globalID': $feature.globalID, attributes: {ispush: 1}}]});
    }
    else {
        return;
    }
    console({'edit': payload});

    return {'edit': payload};
}

// Process starts here
if (IndexOf([1,2,3,9,15,16,17,18,19,7], $feature.assetgroup) == -1) {
    return;
}
if ($feature.ispush == 1) return {"result": {"attributes": {"ispush": 0}}};
console(`Feature: ${$feature.globalID} triggered update_nsp_stateq and ispush is false`);
main();
0 Kudos