diff --git a/part.go b/part.go index a40a6a5..423e9cf 100644 --- a/part.go +++ b/part.go @@ -1,8 +1,10 @@ package opc import ( + "fmt" "mime" "net/url" + "path/filepath" "strings" ) @@ -28,6 +30,21 @@ func (p *Part) validate() error { var defaultRef, _ = url.Parse("http://defaultcontainer/") +// ResolveRelationship returns the absolute URI (from the package root) of the part pointed by a relationship of a source part. +// This method should be used in places where we have a target relationship URI and we want to get the +// name of the part it targets with respect to the source part. +// The source can be a valid part URI, for part relationships, or "/", for package relationships. +func ResolveRelationship(source string, rel string) string { + if !strings.HasPrefix(rel, "/") && !strings.HasPrefix(rel, "\\") { + sourceDir := strings.Replace(filepath.Dir(source), "\\", "/", -1) + if sourceDir == "/" { + return "/" + rel + } + return fmt.Sprintf("%s/%s", sourceDir, rel) + } + return rel +} + // NormalizePartName transforms the input name so it follows the constrains specified in the ISO/IEC 29500-2 ยง9.1.1: // part-URI = 1*( "/" segment ) // segment = 1*( pchar ) diff --git a/part_test.go b/part_test.go index 64d3298..0339696 100644 --- a/part_test.go +++ b/part_test.go @@ -100,3 +100,29 @@ func TestPart_validate(t *testing.T) { }) } } + +func TestResolveRelationship(t *testing.T) { + type args struct { + source string + rel string + } + tests := []struct { + name string + args args + want string + }{ + {"package", args{"/", "c.xml"}, "/c.xml"}, + {"packageWin", args{"\\", "c.xml"}, "/c.xml"}, + {"rel", args{"/3D/3dmodel.model", "c.xml"}, "/3D/c.xml"}, + {"rel", args{"/3D/3dmodel.model", "/3D/box1.model"}, "/3D/box1.model"}, + {"rel", args{"/3D/box3.model", "/2D/2dmodel.model"}, "/2D/2dmodel.model"}, + {"relChild", args{"/3D/box3.model", "2D/2dmodel.model"}, "/3D/2D/2dmodel.model"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ResolveRelationship(tt.args.source, tt.args.rel); got != tt.want { + t.Errorf("ResolveRelationship() = %v, want %v", got, tt.want) + } + }) + } +}