[xwiki-devs] Looking for help with groovy
I am trying to modify the following code so when the user enters a new documentName, it will set the title and rename the document. If I uncomment the saveDocument line, it works. So I know the rest of the code is working. Can anyone see what I am doing wrong? {{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext; class ProcessDocumentRenamer implements EventListener { def xwiki def context ProcessDocumentRenamer(xwiki, context) { this.xwiki = xwiki this.context = context } String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" } List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) } // Called by the Observation Manager when an event matches the list of events returned // by getEvents() void onEvent(Event event, Object source, Object data) { // Current context def crtContext = Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext') // Defines the type of object that should be looked for def myObject = source.getObject("DocumentationTemplates.ProcessClass"); // If the page has an object of the specified class, we get the value of the relevant property and assign it to our documentName variable if (myObject != null) { // Defines the variable that we will later use to update the title of the document def documentName = myObject.get("processName").value // Defines the Complete name we will use later when we rename the document. def FullDocumentName = source.getWikiName() + "!" + source.getSpaceName() + "." + documentName; // If the name has changed, we need to update and rename the document. if (source.getName() != documentName) { source.setTitle(documentName) // Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false); // crtContext.getWiki().saveDocument(source, source.getComment(), source.isMinorEdit(), crtContext); crtContext.getWiki().renamePage(source, FullDocumentName); } } } } // Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}} -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782.htm... Sent from the XWiki- Dev mailing list archive at Nabble.com.
OK, I got the following groovy script to rename the document when it is saved. My problem now is redirecting the browser to the new document. {{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext; class ProcessDocumentRenamer implements EventListener { def xwiki def context ProcessDocumentRenamer(xwiki, context) { this.xwiki = xwiki this.context = context } String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" } List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) } // Called by the Observation Manager when an event matches the list of events returned // by getEvents() void onEvent(Event event, Object source, Object data) { // Current context def crtContext = Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext') // Defines the type of object that should be looked for def myObject = source.getObject("DocumentationTemplates.ProcessClass"); // If the page has an object of the specified class, we get the value of the relevant property and assign it to our title variable if (myObject != null) { // Defines the variable that we will later use to update the title of the document def documentName = myObject.get("processName").value if (source.getName() != documentName) { // Build the new name for the document. def FullDocumentName = source.getSpaceName() + "." + documentName; // Set the document title to the new name. source.setTitle(documentName) // Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false); // Rename the document source.rename(FullDocumentName, crtContext); } } } } // Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}} -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
Groovy runs at javascript in the browser? Is that correct? I added the redirect line below the rename line and it didn't work. {{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext; class ProcessDocumentRenamer implements EventListener { def xwiki def context ProcessDocumentRenamer(xwiki, context) { this.xwiki = xwiki this.context = context } String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" } List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) } // Called by the Observation Manager when an event matches the list of events returned // by getEvents() void onEvent(Event event, Object source, Object data) { // Current context def crtContext = Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext') // Defines the type of object that should be looked for def myObject = source.getObject("DocumentationTemplates.ProcessClass"); // If the page has an object of the specified class, we get the value of the relevant property and assign it to our title variable if (myObject != null) { // Defines the variable that we will later use to update the title of the document def documentName = myObject.get("processName").value if (source.getName() != documentName) { // Build the new name for the document. def FullDocumentName = source.getSpaceName() + "." + documentName; // Set the document title to the new name. source.setTitle(documentName) // Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false); // Rename the document source.rename(FullDocumentName, crtContext); *response.sendRedirect($xwiki.getURL(FullDocumentName));* } } } } // Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}} Anyone have any idea why? -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
On 03/25/2014 01:46 PM, DeHaynes wrote:
response.sendRedirect($xwiki.getURL(FullDocumentName));
$xwiki is Velocity syntax. Just remove the $ and it should work. -- Sergiu Dumitriu http://purl.org/net/sergiu
Good catch, but it still doesn't work. I am thinking that because it is setting up a listener that maybe it is a separate process from the save process and therefore it cannot perform a redirect? -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
On 03/25/2014 02:19 PM, DeHaynes wrote:
Good catch, but it still doesn't work. I am thinking that because it is setting up a listener that maybe it is a separate process from the save process and therefore it cannot perform a redirect?
Yes. You have to get the current response object. The quickest way is to use: crtContext.response.sendRedirect(xwiki.getURL(FullDocumentName)) -- Sergiu Dumitriu http://purl.org/net/sergiu
Didn't work either. I even tried remarking the renaming line out and just do a redirect to a static page. // source.rename(FullDocumentName, crtContext); crtContext.response.sendRedirect(xwiki.getURL("Main.WebHome")) Still didn't work. -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
On Tue, Mar 25, 2014 at 8:28 PM, DeHaynes <ew1560@wayne.edu> wrote:
Didn't work either. I even tried remarking the renaming line out and just do a redirect to a static page.
// source.rename(FullDocumentName, crtContext); crtContext.response.sendRedirect(xwiki.getURL("Main.WebHome"))
Still didn't work.
Save action does its own redirect to view mode at the end (after your listener is called) which overwrites, I think, your redirect. See https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwik... . The redirect done by the Save action take into account the xredirect request parameter though, so an option is to wrap the request and to "overwrite/add" the value of this parameter. Hope this helps, Marius
-- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
I don't understand what you mean by "Wrap this request". How would I do that? -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
See http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequestWra... and http://stackoverflow.com/questions/17601279/use-servlet-filter-to-remove-a-f... as an example. Hope this helps, Marius On Wed, Mar 26, 2014 at 2:35 PM, DeHaynes <ew1560@wayne.edu> wrote:
I don't understand what you mean by "Wrap this request". How would I do that?
-- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
I apologize for my ignorance, but I am not a Java web developer. I have never heard of velocity or groovy until a month ago when I started looking at XWiki. I have a couple years of experience doing ASP.Net development. So when I looked at HttpServletRequestWrapper, I have no idea what I am looking at.
From what I read a servlet is a Java programming language class used on a server. Most of the time it is a web server.
I do not understand how this RequestWrapper integrates with a request. Therefore I do not know how I should use this class. I looked at your example link. From that I think I should * Create a class that extends HttpServletRequestWrapper. * Create a public property for xredirect * put this class in my groovy section of my xwiki page I don't know * How would my class get populated with the existing request Marius, I appreciate your help, but I am lost. :) ________________________________________ Tim Hays -----Original Message----- From: devs [mailto:devs-bounces@xwiki.org] On Behalf Of Marius Dumitru Florea Sent: Wednesday, March 26, 2014 11:13 AM To: XWiki Developers Subject: Re: [xwiki-devs] Looking for help with groovy See http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequestW rapper.html and http://stackoverflow.com/questions/17601279/use-servlet-filter-to-remove-a -form-parameter-from-posted-data as an example. Hope this helps, Marius On Wed, Mar 26, 2014 at 2:35 PM, DeHaynes <ew1560@wayne.edu> wrote:
I don't understand what you mean by "Wrap this request". How would I do that?
-- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp75897 82p7589818.html Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
I feel like I am so close, but it just is not working. I have the following code but it is throwing an error. I will attach a screenshot of the error. (My company is blocking SSH all of a sudden. So I cannot copy the file.) It is saying there is no such property. I assume it means the "xredirect"? {{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class RequestWrapper extends HttpServletRequestWrapper { private HashMap params = new HashMap(); public RequestWrapper(HttpServletRequest request) { super(request); } public String getParameter(String name) { // if we added one, return that one if ( params.get( name ) != null ) { return params.get( name ); } // otherwise return what's in the original request HttpServletRequest req = (HttpServletRequest) super.getRequest(); return req.getParameter( name ); } public void addParameter( String name, String value ) { params.put( name, value ); } } class ProcessDocumentRenamer implements EventListener { def xwiki def context def response ProcessDocumentRenamer(xwiki, context) { this.xwiki = xwiki this.context = context } String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" } List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) } // Called by the Observation Manager when an event matches the list of events returned // by getEvents() void onEvent(Event event, Object source, Object data) { // Current context def crtContext = Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext') def response = Utils.getComponent(Execution.class).getContext().getProperty('response') // Defines the type of object that should be looked for def myObject = source.getObject("DocumentationTemplates.ProcessClass"); // If the page has an object of the specified class, we get the value of the relevant property and assign it to our title variable if (myObject != null) { // Defines the variable that we will later use to update the title of the document def documentName = myObject.get("processName").value if (source.getName() != documentName) { // Build the new name for the document. def FullDocumentName = source.getSpaceName() + "." + documentName; // Set the document title to the new name. source.setTitle(documentName) // Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false); // Rename the document source.rename(FullDocumentName, crtContext); def RedirectRequest = new RequestWrapper(request); RedirectRequest.addParameter('xredirect',xwiki.getURL(FullDocumentName)); } } } } // Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}} <http://xwiki.475771.n2.nabble.com/file/n7589834/Error.png> -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
On Wed, Mar 26, 2014 at 11:00 PM, DeHaynes <ew1560@wayne.edu> wrote:
I feel like I am so close, but it just is not working. I have the following code but it is throwing an error. I will attach a screenshot of the error. (My company is blocking SSH all of a sudden. So I cannot copy the file.) It is saying there is no such property. I assume it means the "xredirect"?
{{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper;
public class RequestWrapper extends HttpServletRequestWrapper
public class RequestWrapper extends HttpServletRequestWrapper implements XWikiRequest (you need to implement XWikiRequest to be able to call XWikiContext#setRequest(XWikiRequest) below)
{ private HashMap params = new HashMap();
public RequestWrapper(HttpServletRequest request) { super(request); }
public String getParameter(String name) { // if we added one, return that one if ( params.get( name ) != null ) { return params.get( name ); }
// otherwise return what's in the original request HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter( name ); }
public void addParameter( String name, String value ) { params.put( name, value ); }
}
class ProcessDocumentRenamer implements EventListener { def xwiki def context def response
ProcessDocumentRenamer(xwiki, context) {
this.xwiki = xwiki this.context = context
You don't need this and it's not even recommended to keep a reference to the xwiki and context object from the moment the event was created. The event listener should use (as you did below) the context from when the event is fired.
}
String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" }
List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) }
// Called by the Observation Manager when an event matches the list of events returned // by getEvents() void onEvent(Event event, Object source, Object data) { // Current context def crtContext = Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext') def response = Utils.getComponent(Execution.class).getContext().getProperty('response')
// Defines the type of object that should be looked for def myObject = source.getObject("DocumentationTemplates.ProcessClass");
// If the page has an object of the specified class, we get the value of the relevant property and assign it to our title variable if (myObject != null) { // Defines the variable that we will later use to update the title of the document def documentName = myObject.get("processName").value
if (source.getName() != documentName) { // Build the new name for the document.
def FullDocumentName = source.getSpaceName() + "." + documentName;
It's recommended to use DocumentReference instead: def newDocRef = new DocumentReference(documentName, source.getDocumentReference().getLastSpaceReference())
// Set the document title to the new name. source.setTitle(documentName)
// Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false);
// Rename the document source.rename(FullDocumentName, crtContext);
def RedirectRequest = new RequestWrapper(request);
RedirectRequest.addParameter('xredirect',xwiki.getURL(FullDocumentName));
RedirectRequest.addParameter('xredirect', source.getURL('view', crtContext)); crtContext.setRequest(RedirectRequest); Hope this helps, Marius
} } } }
// Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}}
<http://xwiki.475771.n2.nabble.com/file/n7589834/Error.png>
-- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
Thank you all VERY much. I got it working. However, you said
def FullDocumentName = source.getSpaceName() + "." + documentName;
It's recommended to use DocumentReference instead: def newDocRef = new DocumentReference(documentName, source.getDocumentReference().getLastSpaceReference())
I am not sure what you are telling me. In this step, I am getting the space name for the current document and combining it with the name the user specified in the field. I looked up "DocumentReference" in the Wiki API and it took me here. http://extensions.xwiki.org/xwiki/bin/view/Extension/Model+Module I don't see how to get the space name from a DocumentReference. -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
This code will take the text from a field on the form and set the form title to the text. It will also rename the document to the specified text. Finally it will redirect the XWiki to the newly named document. This all happens when the user saves the document. I have commented a large part of the code for myself and anyone else trying to understand. {{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; // The main purpose of this class is to allow us to change/add the 'xredirect' parameter on the request. Because we are renaming the document // in the ProcessDocumentRenamer, if we don't redirect the browser to the new document name, they will get a message saying the document they // just saved doesn't exist or has been deleted. // This class wraps the HttpServletRequest class from the context. The reason we do this is so we can access the contents of the request. // There is a property('xredirect') that we want to change to point at our renamed document. // This also implements XWikiRequest interface. The reason we do this is because this interface is how we access the 'xredirect' parameter. public class RequestWrapper extends HttpServletRequestWrapper implements XWikiRequest { // Used to hold the parameters. private HashMap params = new HashMap(); // The class constructor. It takes the HttpServletRequest, object that it is going to wrap, as an input parameter. public RequestWrapper(HttpServletRequest request) { // I do not know what super does? Do anybody else know? super(request); } // Gets parameters from the class. public String getParameter(String name) { // if we added one, return that one if ( params.get( name ) != null ) { return params.get( name ); } // otherwise return what's in the original request. HttpServletRequest req = (HttpServletRequest) super.getRequest(); return req.getParameter( name ); } // Method to add parameters to a class. We will use this when we add 'xredirect'. public void addParameter( String name, String value ) { params.put( name, value ); } // This is needed to meet the XWikiRequest interface requirements. Since the request is already an XWikiRequest, I just // box it and pass the parameter through as the return value. public String get(String name) { return ((XWikiRequest)this).get(name); } // This is needed to meet the XWikiRequest interface requirements. Since the request is already an XWikiRequest, I just // box it and pass the parameter through as the return value. public javax.servlet.http.Cookie getCookie(String cookieName) { return ((XWikiRequest)this).getCookie(cookieName); } // This is needed to meet the XWikiRequest interface requirements. Since the request is already an XWikiRequest, I just // box it and pass it as the return value. public javax.servlet.http.HttpServletRequest getHttpServletRequest() { return ((javax.servlet.http.HttpServletRequest)this); } } // The main purpose of this class is to rename and re-title a document of type "DocumentationTemplates.ProcessClass" to the title // specified by the user in the "processName" field within the document. This class is a listener that waits for the // "DocumentCreateEvent" or "DocumentUpdateEvents" for the "DocumentationTemplates.ProcessClass". It then checks to see if the // current document name matches the "processName" field. If it doesn't, it will rename and re-title the document to what is // specified in the "processName" field. It will then use the "RequestWrapper" to direct the user's browser to the new document URL. class ProcessDocumentRenamer implements EventListener { // The "ProcessDocumentRenamer" constructor. The "xwiki" and "context" input parameters are required, but we do not need them, so // nothing is done with them. ProcessDocumentRenamer(xwiki, context) { } // Required to implement the "EventListener" interface. It provides the name of the listener to the system. String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" } // Required to implement the "EventListener" interface. It provides the events that the listener will respond to. List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) } // Called by the Observation Manager when an event matches the list of events returned by getEvents(). void onEvent(Event event, Object source, Object data) { // Defines the type of object we should be looked for. def myObject = source.getObject("DocumentationTemplates.ProcessClass"); // If the page has an object of the specified class, we get the object. if (myObject != null) { // Get the title that the user specified for the document and store it in the variable "NewDocumentName". // We will later use to update the title and name of the document. def NewDocumentName = myObject.get("processName").value // Check if the document name is different than the one the user specified. if (source.getName() != NewDocumentName) { // Build the new name for the document in the format of "SpaceName.PageName". def FullDocumentName = source.getSpaceName() + "." + NewDocumentName; // Set the document title to the new name. source.setTitle(NewDocumentName) // Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false); // Get the current context. It is needed to rename the document. def crtContext = Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext') // Rename the document source.rename(FullDocumentName, crtContext); // Create an instance of the RequestWrapper class and give it the request from the current context. def RedirectRequest = new RequestWrapper(crtContext.getRequest()); // Get the URL for the document (which has already been renamed, so it points to the new location) and // store it in the RedirectRequest. RedirectRequest.addParameter('xredirect', source.getURL('view', crtContext)); // Store the modified request back in the context. crtContext.setRequest(RedirectRequest); } } } } // Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}} -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
With this approach is there a possibility of a collision if two people are editing a "DocumentationTemplates.ProcessClass" at the same time? -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
Maybe you can publish this snippet on extensions.xwiki.org . Thanks, Marius On Mar 27, 2014 8:56 PM, "DeHaynes" <ew1560@wayne.edu> wrote:
This code will take the text from a field on the form and set the form
title
to the text. It will also rename the document to the specified text. Finally it will redirect the XWiki to the newly named document. This all happens when the user saves the document.
I have commented a large part of the code for myself and anyone else trying to understand.
{{groovy}} import org.xwiki.observation.* import org.xwiki.observation.event.* import org.xwiki.bridge.event.* import org.xwiki.context.* import com.xpn.xwiki.web.* import com.xpn.xwiki.* import org.apache.velocity.VelocityContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper;
// The main purpose of this class is to allow us to change/add the 'xredirect' parameter on the request. Because we are renaming the document // in the ProcessDocumentRenamer, if we don't redirect the browser to the new document name, they will get a message saying the document they // just saved doesn't exist or has been deleted. // This class wraps the HttpServletRequest class from the context. The reason we do this is so we can access the contents of the request. // There is a property('xredirect') that we want to change to point at our renamed document. // This also implements XWikiRequest interface. The reason we do this is because this interface is how we access the 'xredirect' parameter. public class RequestWrapper extends HttpServletRequestWrapper implements XWikiRequest { // Used to hold the parameters. private HashMap params = new HashMap();
// The class constructor. It takes the HttpServletRequest, object that it is going to wrap, as an input parameter. public RequestWrapper(HttpServletRequest request) { // I do not know what super does? Do anybody else know? super(request); }
// Gets parameters from the class. public String getParameter(String name) { // if we added one, return that one if ( params.get( name ) != null ) { return params.get( name ); }
// otherwise return what's in the original request. HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter( name ); }
// Method to add parameters to a class. We will use this when we add 'xredirect'. public void addParameter( String name, String value ) { params.put( name, value ); }
// This is needed to meet the XWikiRequest interface requirements. Since the request is already an XWikiRequest, I just // box it and pass the parameter through as the return value. public String get(String name) { return ((XWikiRequest)this).get(name); }
// This is needed to meet the XWikiRequest interface requirements. Since the request is already an XWikiRequest, I just // box it and pass the parameter through as the return value. public javax.servlet.http.Cookie getCookie(String cookieName) { return ((XWikiRequest)this).getCookie(cookieName); }
// This is needed to meet the XWikiRequest interface requirements. Since the request is already an XWikiRequest, I just // box it and pass it as the return value. public javax.servlet.http.HttpServletRequest getHttpServletRequest() { return ((javax.servlet.http.HttpServletRequest)this); } }
// The main purpose of this class is to rename and re-title a document of type "DocumentationTemplates.ProcessClass" to the title // specified by the user in the "processName" field within the document. This class is a listener that waits for the // "DocumentCreateEvent" or "DocumentUpdateEvents" for the "DocumentationTemplates.ProcessClass". It then checks to see if the // current document name matches the "processName" field. If it doesn't, it will rename and re-title the document to what is // specified in the "processName" field. It will then use the "RequestWrapper" to direct the user's browser to the new document URL. class ProcessDocumentRenamer implements EventListener { // The "ProcessDocumentRenamer" constructor. The "xwiki" and "context" input parameters are required, but we do not need them, so // nothing is done with them. ProcessDocumentRenamer(xwiki, context) { }
// Required to implement the "EventListener" interface. It provides the name of the listener to the system. String getName() { // The unique name of this event listener return "ProcessDocumentRenamer" }
// Required to implement the "EventListener" interface. It provides the events that the listener will respond to. List<Event> getEvents() { // The list of events this listener listens to return Arrays.asList(new DocumentCreatedEvent(), new DocumentUpdatedEvent()) }
// Called by the Observation Manager when an event matches the list of events returned by getEvents(). void onEvent(Event event, Object source, Object data) { // Defines the type of object we should be looked for. def myObject = source.getObject("DocumentationTemplates.ProcessClass");
// If the page has an object of the specified class, we get the object. if (myObject != null) { // Get the title that the user specified for the document and store it in the variable "NewDocumentName". // We will later use to update the title and name of the document. def NewDocumentName = myObject.get("processName").value
// Check if the document name is different than the one the user specified. if (source.getName() != NewDocumentName) { // Build the new name for the document in the format of "SpaceName.PageName". def FullDocumentName = source.getSpaceName() + "." + NewDocumentName;
// Set the document title to the new name. source.setTitle(NewDocumentName)
// Force the storage to keep the same version number, so that this looks like a single save event source.setMetaDataDirty(false); source.setContentDirty(false);
// Get the current context. It is needed to rename the document. def crtContext =
Utils.getComponent(Execution.class).getContext().getProperty('xwikicontext')
// Rename the document source.rename(FullDocumentName, crtContext);
// Create an instance of the RequestWrapper class and give it the request from the current context. def RedirectRequest = new RequestWrapper(crtContext.getRequest());
// Get the URL for the document (which has already been renamed, so it points to the new location) and // store it in the RedirectRequest. RedirectRequest.addParameter('xredirect', source.getURL('view', crtContext));
// Store the modified request back in the context. crtContext.setRequest(RedirectRequest); } } } }
// Register against the Observation Manager def observation = Utils.getComponent(ObservationManager.class) observation.removeListener("ProcessDocumentRenamer") def listener = new ProcessDocumentRenamer(xwiki, xcontext) observation.addListener(listener) {{/groovy}}
-- View this message in context:
http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758...
Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
I created an extension entry http://extensions.xwiki.org/xwiki/bin/view/Extension/Self-Renaming+Forms -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
Nice work! Good to see this contribution! 2014-04-01 19:30 GMT+02:00 DeHaynes <ew1560@wayne.edu>:
I created an extension entry
http://extensions.xwiki.org/xwiki/bin/view/Extension/Self-Renaming+Forms
-- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
On Mar 27, 2014 8:26 PM, "DeHaynes" <ew1560@wayne.edu> wrote:
Thank you all VERY much. I got it working. However, you said
def FullDocumentName = source.getSpaceName() + "." + documentName;
It's recommended to use DocumentReference instead: def newDocRef = new DocumentReference(documentName, source.getDocumentReference().getLastSpaceReference())
I am not sure what you are telling me. In this step, I am getting the
space
name for the current document and combining it with the name the user specified in the field.
I looked up "DocumentReference" in the Wiki API and it took me here. http://extensions.xwiki.org/xwiki/bin/view/Extension/Model+Module
I don't see how to get the space name from a DocumentReference.
documentReference.getLastSpaceReference().getName() "last space reference" because we'd like to support nested spaces in the future. Hope this helps, Marius
-- View this message in context:
http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758...
Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
I don't understand. All of the following pieces of data are being pulled from source variable, which is passed in by the XWiki system as a parameter in the onEvent method: * The wiki document * The value of the processName field in the wiki document. * The wiki document's name. * The document Title * The documents Dirty flags. * The URL for the document. And what I think you are telling me is that the source is not a reliable place for getting the document space, because in the future sub-wikis will cause an issue. Is that right? If that is right, then wouldn't I need change where I get the data in the list above also? -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
On Fri, Mar 28, 2014 at 2:55 PM, DeHaynes <ew1560@wayne.edu> wrote:
I don't understand.
All of the following pieces of data are being pulled from source variable, which is passed in by the XWiki system as a parameter in the onEvent method: * The wiki document * The value of the processName field in the wiki document. * The wiki document's name. * The document Title * The documents Dirty flags. * The URL for the document.
And what I think you are telling me is that the source is not a reliable place for getting the document space, because in the future sub-wikis will cause an issue. Is that right?
No! My comment was only about: // Build the new name for the document in the format of "SpaceName.PageName". def FullDocumentName = source.getSpaceName() + "." + NewDocumentName; The format you are referring to is called "document reference". It's actually a string representation of a document reference. It's no recommended to build the string representation of a document reference manually by concatenating strings. The space or page name could contain a dot (in which case it would need to be escaped). Or the format could be changed at some point. That's why I recommended you to use a document reference instead. Note that the rename method that accepts a string (which you are using) is deprecated in favor of the signature that accepts a document reference. So you just have to replace FullDocumentName with a document reference. Hope this helps, Marius
If that is right, then wouldn't I need change where I get the data in the list above also?
-- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com. _______________________________________________ devs mailing list devs@xwiki.org http://lists.xwiki.org/mailman/listinfo/devs
Thank you for the explanation. I have modified the code to use DocumentReferences. I am still having one issue. When the user clicks the "Save & Continue" an Ajax update is done. The code works as expected and renames the document, but because it is Ajax, the page is not updated. So the user: 1. Does not see the title change. 2. Thinks they are still editing the original document. I see that I have two choices. 1. Disable and hide the "Save & Continue" button. 2. Look into modifying the Ajax update process somehow. I would prefer the second option as it is the correct way to handle this. Do you have a suggestion on which way to go and could you point me to something to get me started? Thank you. -- View this message in context: http://xwiki.475771.n2.nabble.com/Looking-for-help-with-groovy-tp7589782p758... Sent from the XWiki- Dev mailing list archive at Nabble.com.
participants (5)
-
DeHaynes -
Guillaume "Louis-Marie" Delhumeau -
Marius Dumitru Florea -
Sergiu Dumitriu -
Timothy Ray Hays