Category Archives: API Editing pages

Working with a bunch of pages

Because I had to work very often with a list of pages I introduced an own class PageArrayList (not Java 5 enabled yet) as a subclass of ArrayList. Every jRQL method which needs to return a list of pages returns an instance of it, so you can immediately get benefit from it’s functionality.

Let’s assume you want to access all pages linked to the list content_pages_list and all block pages linked to container blocks_bottom of the following page.

To get all pages linked to content_pages_list you can use the following lines of code (shortened; without client and project creation).

Page currentPg = project.getPageById("228766");
PageArrayList listChildren1 = currentPg.getListChildPages("content_pages_list");
PageArrayList listChildren2 = currentPg.getListChildPages("content_pages_list", "content_page");

The first method getListChildPages() is straight forward. The second version automatically filter the children by content class. That means, all pages contained in listChildren2 are based only on content class content_page, all other children are not within this list.

Similar to these methods for children of list elements there exists 2 methods for container elements.

PageArrayList containerChildren1 = currentPg.getContainerChildPages("blocks_bottom");
PageArrayList containerChildren2 = currentPg.getContainerChildPages("containerTemplateElementName", "link_table_block");

After explaining how to get a PageArrayList let’s focus on the functionality offered by PageArrayList. I often needed to find a specific page by different criteria, see below how.

listChildren1.findByPageId("pageId");

listChildren1.findByHeadlineStartsWith(“headlinePrefix”);
listChildren1.findByHeadline(“headline”);

listChildren1.findByFilename(“filename”);
listChildren1.findByFilenameEndsWith(“filenameSuffix”);

listChildren1.findByStandardFieldTextValue(“templateElementName”, “search value”);
listChildren1.findByStandardFieldDateValue(“templateElementName”, new ReddotDate());

All these find methods return only the first page matching the criteria or null, if no page is found.

There are some methods available getting a list of specific values from all pages in list.

List<String> collectHeadlines = listChildren1.collectHeadlines();
List<String> collectHeadlinesAndIds = listChildren1.collectHeadlinesAndIds();
List<String> collectTemplateNames = listChildren1.collectTemplateNames();

Set collectLastChangedByUsers = listChildren1.collectLastChangedByUsers();

All collect methods return a list of the same size as the listChildren1 list, except the last method which returns a set with all distinct user which had last modified the children.

The following select methods filter the children by specific criteria.They all return a PageArrayList instance with usually less size.

// by page attribute
listChildren1.selectAllCreatedBy(project.getUserGroupByName("user group name"));
listChildren1.selectAllLastChangedBy("user name");
listChildren1.selectAllLastChangedOnBefore(10);
listChildren1.selectAllLastChangedOnBefore(new ReddotDate());

listChildren1.selectAllPagesBasedOn(“content class name”);

listChildren1.selectAllPagesContaining(“templateElementName”);
listChildren1.selectAllPagesNotContaining(“templateElementName”);
listChildren1.selectAllPagesHeadlineStartsWith(“prefix”);

listChildren1.selectAllPagesWithHeadlineIn(headlinesCollection);

// by workflow state
listChildren1.selectAllChangeablePages();
listChildren1.selectAllPagesInStateDraft();
listChildren1.selectAllPagesInStateDraftChanged();
listChildren1.selectAllPagesInStateDraftNew();
listChildren1.selectAllPagesInStateWaitingForCorrection();
listChildren1.selectAllPagesInStateWaitingForRelease();
listChildren1.selectAllPagesInStates(draft, draftNew, draftChanged, waitingForRelease, waitingForCorrection, released);

These should give you an overview of what is available. For detailed information about a specific method, please refer to the javadoc of class PageArrayList.

Editing lists and containers

From the  RQL point of view RedDot CMS handle lists and contains very similar. Therefore I implemented the common functionality into the superclass MultiLink.

You can get a multi link on a page directly. See some examples regarding multi link handling on a page.

Page currentPg = project.getPageById(“4711”);
MultiLink multiLink = currentPg.getMultiLink(“multiLinkTemplateElementName”);
List multiLinks = currentPg.getMultiLinks();
boolean includeReferences = false;
List<MultiLink> multiLinks2 = currentPg.getMultiLinks(includeReferences);

List<MultiLink> linksToThisPage = currentPg.getMultiLinksToThisPage();
MultiLink mainMultiLink = currentPg.getMainMultiLink();

The first block let you get a multi link which is element of page currentPg. The second block will return multi links which reside on other pages. Please refer to javadoc for class Page and search for MultiLink on doc page.

After you know how to get a multi link I want to explain some of the functionality. The following methods can be called on instances of List and Container in the same way.

A multi link offers methods from the following areas:

  • create and connect a page (5 methods)
  • connect to an existing page (4 methods)
  • move child pages from and to other multi links (not a standard method in RedDot CMS, but often needed) (10 methods)
  • disconnect child pages (4 methods)
  • access children itself and lists of child page attribute values (5 methods)
  • referencing (3 methods)
  • sort child pages by several criteria (11 methods)
  • link and unlink workflow, authorisation and publication packages (5 methods)
  • pre-assigned content class handling (e.g. check if content class is allowed or return all not allowed children) (6 methods)

For every area there are several methods available to address specific needs. Please get your own impression and examine the javadoc for class MultiLink. Only the subclass List is of further interest. It offers functions for target container editing in addition.

Edit several elements on a page with only one RQL command

All update methods in the style of set*Value(“templateElementName”, “new value”) immediately triggers an RQL command.

If you do so for several page elements the performance would be quite poor. To address this, jRQL offers a way to combine updates on several page elements into only one RQL command.

See the following lines how to achieve this better performance updating several elements on one page.

// 1. step – prepare the page
Page currentPg = project.getPageById(“4711”);
currentPg.startSetElementValues();

// 2. step – remember new page element values only
currentPg.addSetOptionListValue(“templateElementName”, “value”);
currentPg.addSetStandardFieldDateValue(“templateElementName”, new ReddotDate());
currentPg.addSetStandardFieldNumericValue(“templateElementName”, 20);
currentPg.addSetStandardFieldTextValue(“templateElementName”, “text value”);
currentPg.addSetStandardFieldUserDefinedValue(“templateElementName”, “value”);

// 3. step – build a combined update RQL command and trigger it
currentPg.endSetElementValues();

The first step simply empty the internally used list to remember the page element values and prepare so for step 2. You can use any method used in step 2 as often as you want – as long as they are on the same page.  Step 3 itself calls the CMS with only one RQL command and therefore boosts performance.

Neiter are text elements nor image or media element supported for a combined update. But you can trigger updates on these kind of elements at any time beside you are collecting new element values.

Editing texts

Text elements in RedDot CMS can be either of type ASCII or HTML. jRQL supports both with the following methods.

Let us start with some basic check methods if a value is entered by an user or the text element did not have a value. jRQL always returns the default value from the content class element automatically, if available.

String logonGuid="6EB1C39F6A584ABBB9DBB6D36E27FAD7";
String sessionKey="36E1E61495654EB8A4505AC604925FCA";
String projectGuid="73671509FA5C43ED8FC4171AD0298AD2";

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

Page currentPg = project.getPageById(“4711”);
boolean textEmpty = currentPg.isTextEmpty(“templateElementName”);
boolean textValueEntered = currentPg.isTextValueEntered(“templateElementName”);

Method isEmpty() returns true, if there is no default value in content class element and text element on page is not filled. Method isTextValueEntered() returns true, if the text element on the page currently has a text, regardless from where it comes – from the page element or the content class element’s default value.

String textValue = currentPg.getTextValue("templateElementName");
currentPg.setTextValue("templateElementName", "htmlSourceCode");
currentPg.enterText("templateElementName", "text editor input");
currentPg.deleteTextValue("templateElementName");

You can get and set the value of text elements. If it is an HTML text element, than you get and shcould set the HTML source code. For an ASCII text element the unchanged value (as entered) will be returned. Especially on an HTML text element the method enterText() would be of interest. It will encode the given text automatically to handle for instance < and > in same way as you would enter the text into the RedDot’s text editor. (For ASCII text elements it will not harm.)

As for all element types you can get the page element from the page to access additional methods. I want to show you this style here to find out what kind of text element it is.

TextElement textElement = currentPg.getTextElement("templateElementName");
textElement.isAsciiText();
textElement.isHtmlText();

There is support for copying text values from one page to another with several copyText* methods. For further details, please refer to the javadoc of class Page and TextElement.

Editing images

Because images are quite important jRQL offers several ways to work with image elements on a page.

Let’s start with checking an image element if it is empty or a user has entered a value. What is the difference you might ask. Because for every request for a value (=filename) jRQL considers to return the default value from the content class element. Therefore it can be empty (no default value and no image choosen), can have a default value or an user has choosen an image.

String logonGuid="6EB1C39F6A584ABBB9DBB6D36E27FAD7";
String sessionKey="36E1E61495654EB8A4505AC604925FCA";
String projectGuid="73671509FA5C43ED8FC4171AD0298AD2";

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

Page currentPg = project.getPageById(“4711”);
boolean empty = currentPg.isImageEmpty(“templateElementName”);
boolean entered = currentPg.isImageValueEntered(“templateElementName”);

The next lines show you how to get, set and delete an image filename on an image element of currentPg.

String filename = currentPg.getImageValue("templateElementName");
currentPg.setImageValue("templateElementName", "filename");
currentPg.deleteImageValue("templateElementName");

jRQL per default checks if the filename is in the folder and will throw a MissingFileException, if not.

I have implemented the next methods for copying image filenames from one page to another especially for migration purposes. To copy a filename (the image itself has to be in target folder) from another page with same content class element name you can use the next line:

Page sourcePg = project.getPageById("4712");
currentPg.copyImageValueFrom("templateElementName", sourcePg);

The other direction is also supported by the next methods.

Page targetPg = project.getPageById("4713");
ImageElement targetElement = targetPg.getImageElement("templateElementName");
currentPg.copyImageValueTo("sourceTemplateElementName", targetElement);
currentPg.copyImageValueTo("templateElementName", targetPg);

You can even work with references; check if an image element is source of a reference, set a reference or delete a reference.

boolean isRefSource = currentPg.isImageElementReferenceSource("templateElementName");
currentPg.referenceImageElementToImageElement("sourceImageTemplateElementName", "targetImageTemplateElementName");
currentPg.deleteImageElementReference("templateElementName");

And last but not least I implemented a way to download the image itself (from the RedDot image cache).

currentPg.downloadImage("templateElementName", "d:\\temp\\image.png");

I used it to download images from an old project under a well defined filename first, copy and import all image files than manually into the new project’s folder (in file system) and at the end use a jRQL program again to set this new image filenames on the pages in the new project.

Please refer to the javadoc for class ImageElement. It is a subclass of FileElement which is a subclass of Element for further information.

Create a new page

You know now how to access page information and dive from a top page to it’s children.

Now it’s time for the creation of new pages. What do we need? Accordingly to the MS philosophy we need

  1. the template of the new page
  2. a link element (list, container, anchor) where to connect the new page
  3. the headline.

I assume to create a new page on list fields_list on page F5030 of last example. We start with the usual lines of code.

Let get the template (the old name of what is the content class now). To get the template you need the  folder name (=content_templates) and the name of the content class (=field_page) within that folder.

String logonGuid="0904ABF0E43443D2881FE7481339650E";
String sessionKey="490EC675042F4C5A8A6DF1ED63ADD7A6";
String projectGuid="268F46EF5EB74A75824856D3DA1C6597";

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

Template template = project.getTemplateByName(“content_templates”, “field_page”);

Now let’s access our sample page F5030 with page ID34009.

Page currentPg = project.getPageById("34009");

The creation of the new page on that list can be combined in the following line:

Page fieldPg = currentPg.createAndConnectPageAtList("fields_list", template, "new field page", true);

Rember, fields_list is the name of the content class list element and “new field page” is the headline of the new page.

But what’s the boolean at the end? The MS always creates new pages on a list at the top assuming it is a kind of news list. I didn’t want this and so I introduced a flag addAtBottom to be more flexible. If it is true,  the new page will automatically sort at the end of the list. For further details, please check the JavaDoc.

The create method return the newly created page for further access.

Note:

Navigate through the project’s page tree

Assume you want have a page within a project which has structural elements, like a List or Container. jRQL makes it now easy to access children of the list fields_list or the container blocks_bottom.

Sample page with list and container

Let’s start getting some page information (page last updated by whom and when) for all children of list fields_list.

As explained in the getting started post we need these lines of code first. Don’t forget to replace logonGuid, sessionKey and projectGuid with your current values (you can get these values from the IIS session). The last line access page F5030 which has page ID 34009.

String logonGuid="89CAE058B3DF476F96484982772BE963";
String sessionKey="CBE43738755E4D018198CA7D18A43BDF";
String projectGuid="06BE79A1D9F549388F06F6B649E27152";

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

Page currentPg = project.getPageById(“34009”);

Remember, to access the list fields_list on page F5030 you have to know the template element name. In our case the structural element in the content class is named the same.  The reason for using only content class element names is, that you can change the name of e.g. a list or container element on page level.

Because we are interested only in the children of list fields_list we asked the F5030 page directly for it:

PageArrayList listChildren = currentPg.getListChildPages("fields_list");

Class PageArrayList offers specialized methods for selecting and collecting page details (but not yet Java 5 enabled). Next lines iterate over all pages and log the time and author name of last change on it:


for (Iterator iterator = listChildren.iterator(); iterator.hasNext();) {
Page page = (Page) iterator.next();
 System.out.println(page.getInfoText());
System.out.println(page.getLastChangedByUserName());
System.out.println(page.getLastChangedOnAsddMMyyyyHmma());
}

For this page F5030 I got the following results:

34005 f5030.base.date (field_page)
boettmc
03 Mar 2009 5:27 PM
34004 f5030.currency.code (field_page)
boettmc
03 Mar 2009 5:25 PM
34007 f5030.select.btn (field_page)
boettmc
03 Mar 2009 5:29 PM
34006 f5030.currency.table (field_page)
boettmc
03 Mar 2009 5:34 PM

The method getInfoText() delivers the most important information of a page: page ID, headline and name of content class.  Both  getLastChanged*() methods delivers what you would expect.

In the very same manner you can get the children on the F5030 container blocks_bottom.
Assume you want to check, if the child page of container blocks_bottom is in state released, means not in Task of another author.

if (currentPg.hasContainerChildPages("blocks_bottom")) {
Page child = currentPg.getContainerChildPages("blocks_bottom").first();
System.out.println("page=" + child.getHeadlineAndId());
System.out.println("released=" + child.isInStateSavedAsDraft());
}

This will print like this:

page=F5030 deactivated_fields_table_block (ID 34136)
released=false

First I check, if the container has a page connected at all, because this is optional. The method getHeadlineAndId() write out some page details and the last check tells you if page 34136 is in workflow at any stage.

I am sure you understand now how to navigate top down. If you need a navigation bottom top please have a look into the following methods:

Page parentPg = currentPg.getMainLinkParentPage();
List<MultiLink> multiLinksToThisPage = currentPg.getMultiLinksToThisPage();

The class MultiLink is the common super class of List and Container, but doesn’t cover Anchor content class elements. jRQL has it’s  main focus on lists and containers, but access to Anchors or Dynamic Anchors are available, but limited in some way.

Getting started – get and set standard field values

In my article on the Unofficial RedDot CMS blog I focused on installing the plugins and configure the connection between jRQL and your MS. Follow these instructions to prepare MS for contact from jRQL. You will get 12 plugins which might help.

To get in touch with jRQL I recommend to use it from your favorite IDE. Jar all classes from the path apache-tomcat-6.0.10\webapps\rql_rdug\WEB-INF\classes and put in in your class path.

You are ready now for the first lines of code!

Assume you want to read a value from a StandardField Text from a page within one of your projects.
The easiest way is to re-use your current login information for your jRQL requests. So copy these lines and replace with your GUIDs.

String logonGuid="FFFD75C022BB41F580186D0FB63A6F27";
String sessionKey="DFD154CF95464902A7C3EFEF29FBF3C7";
String projectGuid="268F46EF5EB74A75824856D3DA1C6597";

Afterwards jRQL needs to wrap your session information into objects.

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

jRQL now knows which user you are and what project you are currently use.

In this example I want to get data from page with ID 1234. The following line triggers a RQL search request to get the page GUID and encapsulate it in currentPg.

Page currentPg = project.getPageById("1234");

To access an element value of page 1234 you need to know on which content class (formerly called Template) it is based and what’s the name of the template element is. Template element names are crucial for work with jRQL; whole jRQL is based on these names.

To get the value of StandardField Text column_1_header of page 1234 would read like this:

currentPg.getStandardFieldTextValue("column_1_header");

From your Java experience you can now guess how to update this value on page 1234:

currentPg.setStandardFieldTextValue("column_1_header", "new header value");

Well done! At the end the whole program for easy copying.

String logonGuid=”FFFD75C022BB41F580186D0FB63A6F27″;
String sessionKey=”DFD154CF95464902A7C3EFEF29FBF3C7″;
String projectGuid=”268F46EF5EB74A75824856D3DA1C6597″;

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

Page currentPg = project.getPageById(“1234”);
System.out.println(currentPg.getStandardFieldTextValue(“column_1_header”));
currentPg.setStandardFieldTextValue(“column_1_header”, “new header value”);

Similar setter and getter methods are available for these standard field types:

currentPg.getStandardFieldDateValue(“column_updated”);
currentPg.getStandardFieldNumericValue(“column_width”);
currentPg.getStandardFieldUserDefinedValue(“column_email”);

currentPg.setStandardFieldDateValue(“template element name”, new ReddotDate());
currentPg.setStandardFieldNumericValue(“template element name”, 60);
currentPg.setStandardFieldUserDefinedValue(“template element name”, “my-email@test.test”);

Check the javadoc of class Page.