11package com .marklogic .mgmt .resource .tasks ;
22
3- import com .marklogic .mgmt .resource .AbstractResourceManager ;
43import com .marklogic .mgmt .ManageClient ;
4+ import com .marklogic .mgmt .SaveReceipt ;
5+ import com .marklogic .mgmt .resource .AbstractResourceManager ;
56import com .marklogic .mgmt .resource .requests .RequestManager ;
67import com .marklogic .rest .util .Fragment ;
78
89import java .util .ArrayList ;
910import java .util .List ;
1011
1112/**
12- * A scheduled task doesn't have a name, and the ID is generated by ML, so this class assumes that task-path will be
13- * unique and can thus be used as a way to find an existing task.
14- *
15- * Note that the "groupName" property of this class corresponds to the "group-id" querystring parameter. It's called
13+ * The "groupName" property of this class corresponds to the "group-id" querystring parameter. It's called
1614 * "groupName" because "group-id" is misleading - it's a name, not an ID.
1715 */
1816public class TaskManager extends AbstractResourceManager {
@@ -28,6 +26,32 @@ public TaskManager(ManageClient client, String groupName) {
2826 this .groupName = groupName ;
2927 }
3028
29+ /**
30+ * Tasks are tricky because their unique field is "task-id", but that's generated by MarkLogic - it's not expected
31+ * to be in a payload. So this method has to do some extra work to determine what the task-id is for the given
32+ * payload. It does so by looking for an existing task with the same task-path and task-database as what's in the
33+ * given payload. If one exists, then the task-id from the existing task is used. Otherwise, null is returned.
34+ *
35+ * @param payload
36+ * @return
37+ */
38+ @ Override
39+ protected String getResourceId (String payload ) {
40+ final String taskId = payloadParser .getPayloadFieldValue (payload , "task-id" , false );
41+ if (taskId != null ) {
42+ return taskId ;
43+ }
44+
45+ final String taskPath = payloadParser .getPayloadFieldValue (payload , "task-path" );
46+ final String taskDatabase = payloadParser .getPayloadFieldValue (payload , "task-database" , false );
47+
48+ final String xpath = taskDatabase != null ?
49+ format ("/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s' and t:task-database = '%s']/t:idref" , taskPath , taskDatabase ) :
50+ format ("/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s']/t:idref" , taskPath );
51+
52+ return getAsXml ().getElementValue (xpath );
53+ }
54+
3155 @ Override
3256 public String getResourcesPath () {
3357 return appendGroupId (super .getResourcesPath ());
@@ -58,30 +82,60 @@ protected String[] getUpdateResourceParams(String payload) {
5882
5983 @ Override
6084 protected String getIdFieldName () {
61- return "task-path" ;
62- }
63-
64- public String getTaskIdForTaskPath (String taskPath ) {
85+ return "task-id" ;
86+ }
87+
88+ /**
89+ * Previously, this method only accepted a task-path because that was previously used as the unique ID for a task.
90+ * But since two or more tasks can have the same task-path, this class now uses task-id. To preserve backwards
91+ * compatibility then, this method accepts a task-path or a task-id.
92+ *
93+ * @param taskPathOrTaskId
94+ * @return
95+ */
96+ public String getTaskIdForTaskPath (String taskPathOrTaskId ) {
6597 Fragment f = getAsXml ();
66- String xpath = "/node()/*[local-name(.) = 'list-items']/node()"
67- + "[*[local-name(.) = 'task-path'] = '%s']/*[local-name(.) = 'idref']" ;
68- xpath = String .format (xpath , taskPath );
98+ String xpath = "/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s' or t:idref = '%s']/t:idref" ;
99+ xpath = String .format (xpath , taskPathOrTaskId , taskPathOrTaskId );
69100 String id = f .getElementValue (xpath );
70101 if (id == null ) {
71- throw new RuntimeException ("Could not find a scheduled task with a task-path of: " + taskPath );
102+ throw new RuntimeException ("Could not find a scheduled task with a task-path or task-id of: " + taskPathOrTaskId );
72103 }
73104 return id ;
74105 }
75106
107+ /**
108+ * This accounts for an existing task with either task-path or task-id equal to the given resourceNameOrId.
109+ * This preserves backwards compatibility to when this class used task-path as the ID property.
110+ *
111+ * @param resourceNameOrId
112+ * @param resourceUrlParams
113+ * @return
114+ */
76115 @ Override
77116 public boolean exists (String resourceNameOrId , String ... resourceUrlParams ) {
78117 if (logger .isInfoEnabled ()) {
79118 logger .info ("Checking for existence of resource: " + resourceNameOrId );
80119 }
81120 Fragment f = getAsXml ();
82121 return f .elementExists (format (
83- "/node()/*[local-name(.) = 'list-items']/node()[*[local-name(.) = 'task-path'] = '%s']" ,
84- resourceNameOrId ));
122+ "/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s' or t:idref = '%s']" ,
123+ resourceNameOrId , resourceNameOrId ));
124+ }
125+
126+ /**
127+ * When a task is being created, its resourceId - its task-id - will always be null because MarkLogic generates it.
128+ * This method only needs the resourceId for logging purposes. So it's overridden so that the task-path can be used
129+ * as the resourceId so that the logging is more useful.
130+ *
131+ * @param payload
132+ * @param resourceId
133+ * @return
134+ */
135+ @ Override
136+ protected SaveReceipt createNewResource (String payload , String resourceId ) {
137+ final String taskPath = payloadParser .getPayloadFieldValue (payload , "task-path" , false );
138+ return super .createNewResource (payload , taskPath );
85139 }
86140
87141 public List <String > getTaskPaths () {
0 commit comments