fixing namespace for relationships and making it backwards compatible…#197
fixing namespace for relationships and making it backwards compatible…#197AlexanderWollbrink merged 3 commits intomainfrom
Conversation
AlexanderWollbrink
left a comment
There was a problem hiding this comment.
my fix regarding the relationship namespaces, that falsely didn't get taken over to Eclipse. Thank you for cherry picking @martafullen
There was a problem hiding this comment.
In addition to my comments,
I could find one more place for a namespace change:
"http://www.admin-shell.io/aasx/relationships/aas-suppl"
Shouldn't these also be changed?
|
The fix for the bug is up. |
|
Thank you for the fix. Regarding fix related to "aas-suppl" file, please find my observations below:
The relationship gets created in case of supplementary files. If the AASX package has a supplimentary file, the relationship is found under "/aasx//_rels/<AAS_id>.aas.xml.rel" You can use the below AASX file to reproduce the issue. Please rename the from from .zip to .aasx. If you unzip this file, you will find "AssetAdministrationShell---0F98619F.aas.xml.rels" file, which consists of "aas_suppl" relationship under "\aasx\AssetAdministrationShell---0F98619F\ _rels". Please let me know if you need more information. |
|
Hey @juileetikekar, |
|
In my opinion, we will need to add a code explicitely to handle the namespace change. The current implementation just takes care of "aas_suppl" relationship only in case of adding and deleting file in case of "save" operation. |
|
I tested this with several AASX files that I had and it worked nicely for all the relationships. |
Freezor
left a comment
There was a problem hiding this comment.
In general the changes look fine to me. There are some smaller suggestions from my side. There still would be a lot to improve, but that could also mean to refactor that whole class.
I recommend, that we create unit tests for this class in the near future. That would really help us.
| foreach (var x in xs) | ||
| if (x.SourceUri.ToString() == "/") | ||
| { | ||
| //originPart = package.GetPart(x.TargetUri); |
There was a problem hiding this comment.
nitpicking remove commented code
| break; | ||
| } | ||
| if (originPart == null) | ||
| throw (new Exception("Unable to find AASX origin. Aborting!")); |
There was a problem hiding this comment.
optional: I know it is commonly used here, but normally we should not throw the generic Exception, but use a more specific Exception, like ArgumentNullException, or create in rare cases our own Exception implementations.
further infos
| //if its still null, then try with the old | ||
| //this is to make it backwards compatible | ||
| if (specPart == null) { | ||
| xs = originPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-spec"); |
There was a problem hiding this comment.
The url "http://www.admin-shell.io/aasx/relationships/aas-spec" is used in multiple locations. sometimes with and without the www prefix. The code could be improved by using two const values, so you make an issue only in one location
| xs = originPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-spec"); | ||
| foreach (var x in xs) | ||
| { | ||
| //specPart = package.GetPart(x.TargetUri); |
There was a problem hiding this comment.
| //specPart = package.GetPart(x.TargetUri); |
| foreach (var x in xs) | ||
| if (x.SourceUri.ToString() == "/") | ||
| { | ||
| //originPart = package.GetPart(x.TargetUri); |
There was a problem hiding this comment.
| //originPart = package.GetPart(x.TargetUri); |
| originPart.DeleteRelationship(x.Id); | ||
| originPart.CreateRelationship( | ||
| specPart.Uri, TargetMode.Internal, | ||
| "http://admin-shell.io/aasx/relationships/aas-spec"); |
There was a problem hiding this comment.
The code snippet at lines 796-798, where DeleteRelationship and CreateRelationship methods are called, appears to be duplicated elsewhere in the class. Consider refactoring this repetitive logic into a separate method to reduce duplication. Although I understand that the class is already substantial in size, extracting this logic into a method would improve readability and maintainability.
IDEA
// Refactored method to handle deletion and creation of relationships
private void DeleteAndCreateRelationship(string id, Uri specPartUri)
{
originPart.DeleteRelationship(id);
originPart.CreateRelationship(specPartUri, TargetMode.Internal,
"http://admin-shell.io/aasx/relationships/aas-spec");
}
// Usage of the refactored method
DeleteAndCreateRelationship(x.Id, specPart.Uri);| { | ||
| // get the supplementaries from the package, derived from spec | ||
| xs = specPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-suppl"); | ||
| if(xs == null) xs = specPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-suppl"); |
There was a problem hiding this comment.
The code above is used multiple times across the codebase for retrieving relationships by type and handling a fallback scenario could benefit from a method abstraction to adhere to the DRY principle. Consider creating a method to encapsulate this logic, promoting code reuse and improving maintainability.
Revised version of the code snippet:
// Method to retrieve relationships by type with fallback
private IEnumerable<Relationship> GetRelationshipsByTypeWithFallback(Part specPart, string relationshipType)
{
var relationships = specPart.GetRelationshipsByType(relationshipType);
if (relationships == null)
{
relationships = specPart.GetRelationshipsByType(relationshipType);
}
return relationships;
}
// Usage of the refactored method
var xs = GetRelationshipsByTypeWithFallback(specPart, "http://www.admin-shell.io/aasx/relationships/aas-suppl");| xs = package.GetRelationshipsByType( | ||
| "http://www.admin-shell.io/aasx/relationships/aasx-origin"); | ||
| foreach (var x in xs) | ||
| if (x.SourceUri.ToString() == "/") |
There was a problem hiding this comment.
I strongly recommend to use the Equals comparison method for strings.
| if (x.SourceUri.ToString() == "/") | |
| if (x.SourceUri.Equals("/")) |
==Operator: The==operator compares the references of the string objects. If two strings have the same sequence of characters, but they are stored in different memory locations.Equals()Method: TheEquals()method, on the other hand, compares the actual contents of the strings. It checks whether the sequences of characters in both strings are identical.
|
Just a heads-up: there is a unit tested & battle tested implementation of AASX package: https://github.com/aas-core-works/aas-package3-csharp You might want to consider using it in the future. |
|
My suggestion at this point is to merge the PR into main to unblock other activities. We can continue with the refactoring in next step. @AlexanderWollbrink could you please merge the PR into main? |

… (#690)