bug[TW27058]: Pass desktop client URL to server msWordPreview

Change-Id: I2f5e06ab9a0b6d9642de013dfc7cdfcde1495d86
diff --git a/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/OseeLinkBuilder.java b/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/OseeLinkBuilder.java
index d7503f2..d760ea9 100644
--- a/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/OseeLinkBuilder.java
+++ b/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/OseeLinkBuilder.java
@@ -226,16 +226,16 @@
    }
 
    public String getWordMlLink(LinkType destLinkType, ArtifactReadable artifact, TransactionId txId,
-      PresentationType presentationType, String permanentUrl) {
-      String linkId = getLinkId(destLinkType, artifact, txId, presentationType, permanentUrl);
+      PresentationType presentationType, String desktopClientLoopbackUrl) {
+      String linkId = getLinkId(destLinkType, artifact, txId, presentationType, desktopClientLoopbackUrl);
       String linkText = getLinkText(destLinkType, artifact);
 
       return WordCoreUtil.getLink(destLinkType, linkId, linkText).toString();
    }
 
    public String getWordMlLink(LinkType destLinkType, ArtifactReadable artifact, TransactionId txId,
-      String permanentUrl) {
-      return getWordMlLink(destLinkType, artifact, txId, PresentationType.DEFAULT_OPEN, permanentUrl);
+      String desktopClientLoopbackUrl) {
+      return getWordMlLink(destLinkType, artifact, txId, PresentationType.DEFAULT_OPEN, desktopClientLoopbackUrl);
    }
 
 }
diff --git a/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/publisher/publishing/PublishingRequestData.java b/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/publisher/publishing/PublishingRequestData.java
index 3158938..a86598e 100644
--- a/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/publisher/publishing/PublishingRequestData.java
+++ b/plugins/org.eclipse.osee.define.rest.api/src/org/eclipse/osee/define/rest/api/publisher/publishing/PublishingRequestData.java
@@ -25,6 +25,7 @@
  * Data structure used to request a publish of a tree of artifacts.
  *
  * @author Loren K. Ashley
+ * @author Jaden W. Puckett
  */
 
 public class PublishingRequestData implements ToMessage {
@@ -48,6 +49,14 @@
    private PublishingTemplateRequest publishingTemplateRequest;
 
    /**
+    * The base URL of the user's machine used by {@link WordMlLinkWordMlLinkHandler} to replace 'OSEE_LINK' (artifact
+    * links) in the Word Template Content with loopback links to the user's desktop client. Not required for all
+    * publishing operations.
+    */
+
+   private String desktopClientLoopbackUrl;
+
+   /**
     * Creates a new empty {@link PublishingRequestData} for JSON deserialization.
     */
 
@@ -55,11 +64,13 @@
       this.publishingTemplateRequest = null;
       this.artifactIds = null;
       this.publishingRendererOptions = null;
+      this.desktopClientLoopbackUrl = "";
    }
 
    /**
     * Creates a new {@link PublishingRequestData} with data for serialization (client) or for making a Publishing
-    * Operations service call (server).
+    * Operations service call (server). The {@link #desktopClientLoopbackUrl} is not specified and is set to default
+    * empty string.
     *
     * @param publishingTemplateRequest the request data for the Publishing Template.
     * @param publishingRendererOptions the renderer options for the publish.
@@ -76,6 +87,49 @@
          "PublishingRequest::new, parameter \"publishingRendererOptions\" cannot be null.");
       this.artifactIds =
          Objects.requireNonNull(artifactIds, "MsWordPreviewTemplate::new, parameter \"artifactIds\" cannot be null.");
+      this.desktopClientLoopbackUrl = "";
+   }
+
+   /**
+    * Creates a new {@link PublishingRequestData} with data for serialization (client) or for making a Publishing
+    * Operations service call (server).
+    *
+    * @param publishingTemplateRequest the request data for the Publishing Template.
+    * @param publishingRendererOptions the renderer options for the publish.
+    * @param artifactIds a list of the identifiers of the artifacts to be previewed.
+    * @param desktopClientLoopbackUrl the base URL of the user's machine used by {@link WordMlLinkWordMlLinkHandler} to
+    * replace 'OSEE_LINK' (artifact links) in the Word Template Content with loopback links to the user's desktop
+    * client.
+    * @throws NullPointerException when any of the parameters <code>publishingTemplateRequest</code>,
+    * <code>branchId</code>, or <code>artifactId</code> is <code>null</code>.
+    */
+
+   public PublishingRequestData(PublishingTemplateRequest publishingTemplateRequest, RendererMap publishingRendererOptions, List<ArtifactId> artifactIds, String desktopClientLoopbackUrl) {
+
+      this.publishingTemplateRequest = Objects.requireNonNull(publishingTemplateRequest,
+         "PublishingRequest::new, parameter \"publishingTemplateRequest\" cannot be null.");
+      this.publishingRendererOptions = Objects.requireNonNull(publishingRendererOptions,
+         "PublishingRequest::new, parameter \"publishingRendererOptions\" cannot be null.");
+      this.artifactIds =
+         Objects.requireNonNull(artifactIds, "MsWordPreviewTemplate::new, parameter \"artifactIds\" cannot be null.");
+      this.desktopClientLoopbackUrl = desktopClientLoopbackUrl != null ? desktopClientLoopbackUrl : "";
+   }
+
+   /**
+    * Predicate to test the validity of the {@link MsWordTemplateRequestData} object.
+    *
+    * @return <code>true</code> when all members are non-<code>null</code>, {@link #publishingTemplateRequest} is valid
+    * according to {@link PublishingTemplateRequest#isValid}, and {@link #artifactIds} is not empty; otherwise,
+    * <code>false</code>.
+    */
+
+   public boolean isValid() {
+      //@formatter:off
+      return
+            Objects.nonNull( this.publishingTemplateRequest ) && this.publishingTemplateRequest.isValid()
+         && Objects.nonNull( this.publishingRendererOptions )
+         && Objects.nonNull( this.artifactIds ) && !this.artifactIds.isEmpty();
+      //@formatter:on
    }
 
    /**
@@ -124,20 +178,31 @@
    }
 
    /**
-    * Predicate to test the validity of the {@link MsWordTemplateRequestData} object.
+    * Retrieves the base URL of the user's machine, used for handling links and creating loopback URLs in Word
+    * documents.
     *
-    * @return <code>true</code> when all members are non-<code>null</code>, {@link #publishingTemplateRequest} is valid
-    * according to {@link PublishingTemplateRequest#isValid}, and {@link #artifactIds} is not empty; otherwise,
-    * <code>false</code>.
+    * @return the {@link String} representing the user's machine base URL.
+    * @throws IllegalStateException if the base URL has not been set.
     */
+   public String getDesktopClientLoopbackUrl() {
+      if (Objects.isNull(this.desktopClientLoopbackUrl)) {
+         throw new IllegalStateException("Desktop client loopback URL has not been set.");
+      }
+      return this.desktopClientLoopbackUrl;
+   }
 
-   public boolean isValid() {
-      //@formatter:off
-      return
-            Objects.nonNull( this.publishingTemplateRequest ) && this.publishingTemplateRequest.isValid()
-         && Objects.nonNull( this.publishingRendererOptions )
-         && Objects.nonNull( this.artifactIds ) && !this.artifactIds.isEmpty();
-      //@formatter:on
+   /**
+    * Sets the base URL of the user's machine, which is used for handling links and creating loopback URLs in Word
+    * documents. If null, set the url to empty string.
+    *
+    * @param desktopClientLoopbackUrl a {@link String} representing the user's machine base URL.
+    */
+   public void setDesktopClientLoopbackUrl(String desktopClientLoopbackUrl) {
+      if (desktopClientLoopbackUrl != null) {
+         this.desktopClientLoopbackUrl = desktopClientLoopbackUrl;
+      } else {
+         this.desktopClientLoopbackUrl = "";
+      }
    }
 
    /**
@@ -226,7 +291,6 @@
    public String toString() {
       return this.toMessage(0, null).toString();
    }
-
 }
 
 /* EOF */
diff --git a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/PublishingOperationsImpl.java b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/PublishingOperationsImpl.java
index 9c7d763..b5d6975 100644
--- a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/PublishingOperationsImpl.java
+++ b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/PublishingOperationsImpl.java
@@ -571,7 +571,8 @@
              .configure
                 (
                    publishingTemplate,
-                   publishingRendererOptions
+                   publishingRendererOptions,
+                   publishingRequestData.getDesktopClientLoopbackUrl()
                 )
              .applyTemplate
                 (
diff --git a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateContentRendererHandler.java b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateContentRendererHandler.java
index 3edfaf5..79110b0 100644
--- a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateContentRendererHandler.java
+++ b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateContentRendererHandler.java
@@ -105,7 +105,7 @@
                      wtcData.getTxId(),
                      unknownGuids,
                      wtcData.getPresentationType(),
-                     wtcData.getPermanentLinkUrl(),
+                     wtcData.getDesktopClientLoopbackUrl(),
                      wtcData.getIncludeBookmark()
                   );
             //@formatter:on
@@ -137,7 +137,7 @@
                   wtcData.getTxId(),
                   unknownGuids,
                   wtcData.getPresentationType(),
-                  wtcData.getPermanentLinkUrl(),
+                  wtcData.getDesktopClientLoopbackUrl(),
                   wtcData.getIncludeBookmark()
                );
          //@formatter:on
diff --git a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateProcessorServer.java b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateProcessorServer.java
index fe798da..10fce09 100644
--- a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateProcessorServer.java
+++ b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/operations/publisher/publishing/WordTemplateProcessorServer.java
@@ -30,7 +30,6 @@
 import org.eclipse.osee.activity.api.ActivityLog;
 import org.eclipse.osee.ats.api.AtsApi;
 import org.eclipse.osee.define.operations.api.publisher.datarights.DataRightsOperations;
-import org.eclipse.osee.define.rest.api.ArtifactUrlServer;
 import org.eclipse.osee.define.rest.api.AttributeAlphabeticalComparator;
 import org.eclipse.osee.define.rest.api.OseeHierarchyComparator;
 import org.eclipse.osee.framework.core.OrcsTokenService;
@@ -203,7 +202,7 @@
 
    protected boolean overrideOutlineNumber;
 
-   protected final String permanentLinkUrl;
+   protected String desktopClientLoopbackUrl;
 
    /**
     * Tracks artifacts that have been processed by {@link ArtifactId} and GUID.
@@ -275,7 +274,7 @@
       this.outlineNumber = null;
       this.overrideClassification = null;
       this.overrideOutlineNumber = false;
-      this.permanentLinkUrl = new ArtifactUrlServer(this.orcsApi).getSelectedPermanentLinkUrl();
+      this.desktopClientLoopbackUrl = null;
       this.processedArtifactTracker = new ProcessedArtifactTracker();
       //@formatter:off
       this.publishingArtifactLoader =
@@ -541,7 +540,8 @@
 
    }
 
-   public WordTemplateProcessorServer configure(PublishingTemplate publishingTemplate, RendererMap publishingOptions) {
+   public WordTemplateProcessorServer configure(PublishingTemplate publishingTemplate, RendererMap publishingOptions,
+      String desktopClientLoopbackUrl) {
 
       /*
        * Publishing Template
@@ -555,6 +555,13 @@
 
       this.renderer = publishingOptions;
 
+      /**
+       * The base URL of the user's machine used by {@link WordMlLinkWordMlLinkHandler} to replace 'OSEE_LINK' (artifact
+       * links) in the Word Template Content with loopback links to the user's desktop client.
+       */
+
+      this.desktopClientLoopbackUrl = desktopClientLoopbackUrl;
+
       /*
        * All Attributes
        */
@@ -1297,7 +1304,7 @@
               presentationType,
               label,
               footer,
-              this.permanentLinkUrl,
+              this.desktopClientLoopbackUrl,
               this.publishingArtifactLoader.isChangedArtifact(artifact),
               includeBookmark,
               artifact.isHistorical()
diff --git a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/internal/wordupdate/WordMlLinkHandler.java b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/internal/wordupdate/WordMlLinkHandler.java
index 1ad364d..420713d 100644
--- a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/internal/wordupdate/WordMlLinkHandler.java
+++ b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/internal/wordupdate/WordMlLinkHandler.java
@@ -133,7 +133,7 @@
     */
 
    public static String link(QueryFactory queryFactory, LinkType destLinkType, ArtifactReadable source, String content,
-      TransactionId txId, Set<String> unknownGuids, PresentationType presentationType, String permanentUrl,
+      TransactionId txId, Set<String> unknownGuids, PresentationType presentationType, String desktopClientLoopbackUrl,
       IncludeBookmark includeBookmark) {
 
       LinkType linkType = checkLinkType(destLinkType);
@@ -153,7 +153,7 @@
 
       if (!matchMap.isEmpty()) {
          modified = modifiedContent(queryFactory, linkType, source, content, matchMap, false, txId, unknownGuids,
-            presentationType, permanentUrl);
+            presentationType, desktopClientLoopbackUrl);
       }
 
       if (includeBookmark.isYes() && (linkType != LinkType.OSEE_SERVER_LINK)) {
@@ -329,7 +329,7 @@
 
    private static String modifiedContent(QueryFactory queryFactory, LinkType destLinkType, ArtifactReadable source,
       String original, HashCollection<String, MatchRange> matchMap, boolean isUnlinking, TransactionId txId,
-      Set<String> unknown, PresentationType presentationType, String permanentUrl) {
+      Set<String> unknown, PresentationType presentationType, String desktopClientLoopbackUrl) {
       BranchId branch = source.getBranch();
       ChangeSet changeSet = new ChangeSet(original);
       List<ArtifactReadable> artifactsFromSearch = null;
@@ -380,8 +380,9 @@
                   var replaceWith = WordCoreUtil.getOseeLinkMarker(artifact.getGuid());
                   changeSet.replace(match.start(), match.end(), replaceWith);
                } else {
+               // Replace with user's desktop client loopback url
                   var replaceWith =
-                     linkBuilder.getWordMlLink(destLinkType, artifact, txId, presentationType, permanentUrl);
+                     linkBuilder.getWordMlLink(destLinkType, artifact, txId, presentationType, desktopClientLoopbackUrl);
                   changeSet.replace(match.start(), match.end(), replaceWith);
                }
             }
@@ -393,8 +394,9 @@
                   var replaceWith = WordCoreUtil.getOseeLinkMarker(artifact.getIdString());
                   changeSet.replace(match.start(), match.end(), replaceWith);
                } else {
+                  // Replace with user's desktop client loopback url
                   var replaceWith =
-                     linkBuilder.getWordMlLink(destLinkType, artifact, txId, presentationType, permanentUrl);
+                     linkBuilder.getWordMlLink(destLinkType, artifact, txId, presentationType, desktopClientLoopbackUrl);
                   changeSet.replace(match.start(), match.end(), replaceWith);
                }
             }
diff --git a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/publishing/PublishingEndpointImpl.java b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/publishing/PublishingEndpointImpl.java
index 1051eaa..860af20 100644
--- a/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/publishing/PublishingEndpointImpl.java
+++ b/plugins/org.eclipse.osee.define/src/org/eclipse/osee/define/rest/publishing/PublishingEndpointImpl.java
@@ -20,13 +20,11 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
-
 import javax.ws.rs.BadRequestException;
 import javax.ws.rs.NotAuthorizedException;
 import javax.ws.rs.NotFoundException;
 import javax.ws.rs.ServerErrorException;
 import javax.ws.rs.core.Response;
-
 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
 import org.eclipse.osee.define.operations.api.DefineOperations;
 import org.eclipse.osee.define.operations.markdown.MarkdownConverter;
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordRenderUtil.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordRenderUtil.java
index 6a6170f..fe82b20 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordRenderUtil.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordRenderUtil.java
@@ -1825,7 +1825,7 @@
             PresentationType                   presentationType,
             String                             label,
             String                             footer,
-            String                             permanentLinkUrl,
+            String                             desktopClientLoopbackUrl,
             boolean                            artifactIsChanged,
             IncludeBookmark                    includeBookmark,
             TransactionToken                   historicalArtifactTransactionToken,
@@ -1857,7 +1857,7 @@
       wtcData.setLinkType(rendererMap.getRendererOptionValue(RendererOption.LINK_TYPE));
       wtcData.setPresentationType(presentationType);
       wtcData.setTxId(historicalArtifactTransactionToken);
-      wtcData.setPermanentLinkUrl(permanentLinkUrl);
+      wtcData.setDesktopClientLoopbackUrl(desktopClientLoopbackUrl);
       wtcData.setArtIsChanged(artifactIsChanged);
       wtcData.setIncludeBookmark(safeIncludeBookmark);
 
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordTemplateContentData.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordTemplateContentData.java
index 29e9c59..a7330e9 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordTemplateContentData.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/publishing/WordTemplateContentData.java
@@ -44,7 +44,7 @@
 
    private @Nullable String oseeLink;
 
-   private String permanentLinkUrl;
+   private String desktopClientLoopbackUrl;
 
    private PresentationType presentationType;
 
@@ -99,8 +99,8 @@
       return oseeLink;
    }
 
-   public String getPermanentLinkUrl() {
-      return permanentLinkUrl;
+   public String getDesktopClientLoopbackUrl() {
+      return desktopClientLoopbackUrl;
    }
 
    public PresentationType getPresentationType() {
@@ -153,13 +153,13 @@
    public boolean isValid() {
       //@formatter:off
       return
-            Objects.nonNull( this.artId            )
-         && Objects.nonNull( this.branch           )
-         && Objects.nonNull( this.footer           )
-         && Objects.nonNull( this.permanentLinkUrl )
-         && Objects.nonNull( this.presentationType )
-         && Objects.nonNull( this.txId             )
-         && Objects.nonNull( this.viewId           )
+            Objects.nonNull( this.artId              )
+         && Objects.nonNull( this.branch             )
+         && Objects.nonNull( this.footer             )
+         && Objects.nonNull( this.desktopClientLoopbackUrl )
+         && Objects.nonNull( this.presentationType   )
+         && Objects.nonNull( this.txId               )
+         && Objects.nonNull( this.viewId             )
          ;
       //@formatter:on
    }
@@ -247,20 +247,21 @@
    }
 
    /**
-    * Sets the permanent link URL. Used for deserialization.
+    * Sets the base URL of the user's machine, which is used for handling links and creating loopback URLs in Word
+    * documents. Used for deserialization.
     *
-    * @param permanentLinkUrl the permanent link URL. Maybe an empty {@link String} but not <code>null</code>.
-    * @throws NullPointerException when the parameter <code>permanentLinkUrl</code> is <code>null</code>.
-    * @throws IllegalStateException when the member {@link #permanentLinkUrl} has already been set.
+    * @param desktopClientLoopbackUrl a {@link String} representing the user's machine base URL.
+    * @throws NullPointerException when the parameter <code>desktopClientLoopbackUrl</code> is <code>null</code>.
+    * @throws IllegalStateException when the member {@link #desktopClientLoopbackUrl} has already been set.
     */
 
-   public void setPermanentLinkUrl(String permanentLinkUrl) {
-      if (Objects.nonNull(this.permanentLinkUrl)) {
+   public void setDesktopClientLoopbackUrl(String desktopClientLoopbackUrl) {
+      if (Objects.nonNull(this.desktopClientLoopbackUrl)) {
          throw new IllegalStateException(
-            "WordTemplateContentData::setPermanentLinkUrl, member \"permanentLinkUrl\" has already been set.");
+            "WordTemplateContentData::desktopClientLoopbackUrl, member \"desktopClientLoopbackUrl\" has already been set.");
       }
-      this.permanentLinkUrl = Objects.requireNonNull(permanentLinkUrl,
-         "WordTemplateContentData::setPermanentLinkUrl, parameter \"permanentLinkUrl\" cannot be null.");
+      this.desktopClientLoopbackUrl = Objects.requireNonNull(desktopClientLoopbackUrl,
+         "WordTemplateContentData::setDesktopClientLoopbackUrl, parameter \"desktopClientLoopbackUrl\" cannot be null.");
    }
 
    /**
@@ -328,19 +329,19 @@
       outMessage
          .indent( indent )
          .title( "WordTemplateContentData" )
-         .indentInc()
-         .segment( "artId",            this.artId            )
-         .segment( "artIsChanged",     this.artIsChanged     )
-         .segment( "branch",           this.branch           )
-         .segment( "footer",           this.footer           )
-         .segment( "isEdit",           this.isEdit           )
-         .segment( "linkType",         this.linkType         )
-         .segment( "oseeLink",         this.oseeLink         )
-         .segment( "permanentLinkUrl", this.permanentLinkUrl )
-         .segment( "presentationType", this.presentationType )
-         .segment( "sessionId",        this.sessionId        )
-         .segment( "txId",             this.txId             )
-         .segment( "viewId",           this.viewId           )
+         .indentInc()                     
+         .segment( "artId",               this.artId               )
+         .segment( "artIsChanged",        this.artIsChanged        )
+         .segment( "branch",              this.branch              )
+         .segment( "footer",              this.footer              )
+         .segment( "isEdit",              this.isEdit              )
+         .segment( "linkType",            this.linkType            )
+         .segment( "oseeLink",            this.oseeLink            )
+         .segment( "desktopClientLoopbackUrl",  this.desktopClientLoopbackUrl  )
+         .segment( "presentationType",    this.presentationType    )
+         .segment( "sessionId",           this.sessionId           )
+         .segment( "txId",                this.txId                )
+         .segment( "viewId",              this.viewId              )
          .indentDec()
          ;
       //@formatter:on
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/MarkdownRenderer.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/MarkdownRenderer.java
index e13ddee..e9abd2f 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/MarkdownRenderer.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/MarkdownRenderer.java
@@ -23,6 +23,7 @@
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.osee.define.rest.api.publisher.publishing.PublishingRequestData;
 import org.eclipse.osee.define.rest.api.publisher.templatemanager.PublishingTemplateRequest;
+import org.eclipse.osee.framework.core.client.ClientSessionManager;
 import org.eclipse.osee.framework.core.data.ArtifactId;
 import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
 import org.eclipse.osee.framework.core.data.AttributeTypeToken;
@@ -427,9 +428,10 @@
       var publishingRequestData =
          new PublishingRequestData
                 (
-                   publishingTemplateRequest, /* Publishing Template Request */
-                   this,                      /* Renderer Options            */
-                   artifactIdentifiers        /* Artifacts To Publish        */
+                   publishingTemplateRequest,                                                                                   /* Publishing Template Request */
+                   this,                                                                                                        /* Renderer Options            */
+                   artifactIdentifiers,                                                                                         /* Artifacts To Publish        */
+                   String.format("http://%s:%s/", ClientSessionManager.getClientName(), ClientSessionManager.getClientPort())   /* User's Machine's Base URL   */
                 );
       //@formatter:on
 
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/WordTemplateRenderer.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/WordTemplateRenderer.java
index 1fe95c8..9c40a1b 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/WordTemplateRenderer.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/WordTemplateRenderer.java
@@ -752,9 +752,10 @@
       var publishingRequestData =
          new PublishingRequestData
                 (
-                   publishingTemplateRequest, /* Publishing Template Request */
-                   this,                      /* Renderer Options            */
-                   artifactIdentifiers        /* Artifact To Publish         */
+                   publishingTemplateRequest,                                                                                     /* Publishing Template Request */
+                   this,                                                                                                          /* Renderer Options            */
+                   artifactIdentifiers,                                                                                           /* Artifact To Publish         */
+                   String.format("http://%s:%s/", ClientSessionManager.getClientName(), ClientSessionManager.getClientPort())     /* User's Machine's Base URL   */
                 );
       //@formatter:on
 
@@ -998,7 +999,7 @@
          wtcData.setPresentationType(presentationType);
          ArtifactId view = (ArtifactId) getRendererOptionValue(RendererOption.VIEW);
          wtcData.setViewId(view == null ? ArtifactId.SENTINEL : view);
-         wtcData.setPermanentLinkUrl(
+         wtcData.setDesktopClientLoopbackUrl(
             String.format("http://%s:%s/", ClientSessionManager.getClientName(), ClientSessionManager.getClientPort()));
 
          Pair<String, Set<String>> content = null;
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/word/WordTemplateProcessorClient.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/word/WordTemplateProcessorClient.java
index 80b78a0..6479684 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/word/WordTemplateProcessorClient.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/word/WordTemplateProcessorClient.java
@@ -114,7 +114,7 @@
 
    private static final String NESTED_TEMPLATE = "NestedTemplate";
 
-   private static final String staticPermanentLinkUrl =
+   private static final String staticdesktopClientLoopbackUrl =
       String.format("http://%s:%s/", ClientSessionManager.getClientName(), ClientSessionManager.getClientPort());
 
    public static final String STYLES = "<w:lists>.*?</w:lists><w:styles>.*?</w:styles>";
@@ -185,7 +185,7 @@
 
    //private CharSequence paragraphNumber = null;
 
-   private final String permanentLinkUrl;
+   private final String desktopClientLoopbackUrl;
 
    private PresentationType presentationType;
 
@@ -245,7 +245,7 @@
       this.maximumOutlineDepth = null;
       this.outlineNumber = null;
       this.overrideOutlineNumber = false;
-      this.permanentLinkUrl = WordTemplateProcessorClient.staticPermanentLinkUrl;
+      this.desktopClientLoopbackUrl = WordTemplateProcessorClient.staticdesktopClientLoopbackUrl;
       this.presentationType = null;
       this.primaryPublishingTemplate = null;
       this.processedArtifactTracker = new ProcessedArtifactTracker();
@@ -1153,7 +1153,7 @@
                presentationType,
                attributeOptions.getLabel(),
                footer,
-               this.permanentLinkUrl,
+               this.desktopClientLoopbackUrl,
                false,
                includeBookmark,
                artifact.isHistorical()