001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Sun Seng David TAN <stan@nuxeo.com>
018 *     Antoine Taillefer
019 *     Gabriel Barata
020 */
021package org.nuxeo.functionaltests.pages;
022
023import static org.junit.Assert.assertEquals;
024import static org.nuxeo.functionaltests.Constants.FILE_TYPE;
025import static org.nuxeo.functionaltests.Constants.FOLDER_TYPE;
026import static org.nuxeo.functionaltests.Constants.FORUM_TYPE;
027import static org.nuxeo.functionaltests.Constants.NOTE_TYPE;
028import static org.nuxeo.functionaltests.Constants.WORKSPACES_TITLE;
029
030import java.io.IOException;
031import java.util.List;
032import java.util.stream.Collectors;
033
034import org.apache.commons.lang3.StringUtils;
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.nuxeo.functionaltests.AjaxRequestManager;
038import org.nuxeo.functionaltests.Constants;
039import org.nuxeo.functionaltests.Locator;
040import org.nuxeo.functionaltests.Required;
041import org.nuxeo.functionaltests.fragment.AddAllToCollectionForm;
042import org.nuxeo.functionaltests.fragment.AddToCollectionForm;
043import org.nuxeo.functionaltests.pages.actions.ContextualActions;
044import org.nuxeo.functionaltests.pages.admincenter.AdminCenterBasePage;
045import org.nuxeo.functionaltests.pages.forms.CollectionCreationFormPage;
046import org.nuxeo.functionaltests.pages.forms.DublinCoreCreationDocumentFormPage;
047import org.nuxeo.functionaltests.pages.forms.FileCreationFormPage;
048import org.nuxeo.functionaltests.pages.forms.FolderCreationFormPage;
049import org.nuxeo.functionaltests.pages.forms.ForumCreationFormPage;
050import org.nuxeo.functionaltests.pages.forms.NoteCreationFormPage;
051import org.nuxeo.functionaltests.pages.forms.WorkspaceCreationFormPage;
052import org.nuxeo.functionaltests.pages.search.SearchPage;
053import org.nuxeo.functionaltests.pages.tabs.CollectionContentTabSubPage;
054import org.nuxeo.functionaltests.pages.tabs.CommentsTabSubPage;
055import org.nuxeo.functionaltests.pages.tabs.ContentTabSubPage;
056import org.nuxeo.functionaltests.pages.tabs.EditTabSubPage;
057import org.nuxeo.functionaltests.pages.tabs.FilesTabSubPage;
058import org.nuxeo.functionaltests.pages.tabs.ForumTabSubPage;
059import org.nuxeo.functionaltests.pages.tabs.HistoryTabSubPage;
060import org.nuxeo.functionaltests.pages.tabs.ManageTabSubPage;
061import org.nuxeo.functionaltests.pages.tabs.PermissionsSubPage;
062import org.nuxeo.functionaltests.pages.tabs.PublishTabSubPage;
063import org.nuxeo.functionaltests.pages.tabs.RelationTabSubPage;
064import org.nuxeo.functionaltests.pages.tabs.SectionContentTabSubPage;
065import org.nuxeo.functionaltests.pages.tabs.SectionsContentTabSubPage;
066import org.nuxeo.functionaltests.pages.tabs.SummaryTabSubPage;
067import org.nuxeo.functionaltests.pages.tabs.TopicTabSubPage;
068import org.nuxeo.functionaltests.pages.tabs.WorkflowTabSubPage;
069import org.nuxeo.functionaltests.pages.tabs.WorkspacesContentTabSubPage;
070import org.nuxeo.functionaltests.pages.workspace.WorkspaceHomePage;
071import org.openqa.selenium.By;
072import org.openqa.selenium.JavascriptExecutor;
073import org.openqa.selenium.NoSuchElementException;
074import org.openqa.selenium.StaleElementReferenceException;
075import org.openqa.selenium.WebDriver;
076import org.openqa.selenium.WebElement;
077import org.openqa.selenium.support.FindBy;
078
079/**
080 * The nuxeo main document base page
081 *
082 * @author Sun Seng David TAN <stan@nuxeo.com>
083 */
084public class DocumentBasePage extends AbstractPage {
085
086    private static final Log log = LogFactory.getLog(DocumentBasePage.class);
087
088    /**
089     * Exception occurred a user is expected to be connected but it isn't.
090     */
091    public class UserNotConnectedException extends Exception {
092
093        private static final long serialVersionUID = 1L;
094
095        public UserNotConnectedException(String username) {
096            super("The user " + username + " is expected to be connected but isn't");
097        }
098    }
099
100    @FindBy(xpath = "//form[@id='breadcrumbForm']")
101    public WebElement breadcrumbForm;
102
103    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Content']")
104    public WebElement contentTabLink;
105
106    public ContextualActions contextualActions;
107
108    @FindBy(className = "creator")
109    public WebElement currentDocumentContributor;
110
111    @FindBy(className = "documentDescription")
112    public WebElement currentDocumentDescription;
113
114    @FindBy(xpath = "//form[@id='document_header_layout_form']//h1")
115    public WebElement currentDocumentTitle;
116
117    @FindBy(className = "currentDocumentDescription")
118    public WebElement currentFolderishDescription;
119
120    @FindBy(linkText = "WORKSPACE")
121    public WebElement documentManagementLink;
122
123    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Edit']")
124    public WebElement editTabLink;
125
126    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Files']")
127    public WebElement filesTabLink;
128
129    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Permissions']")
130    public WebElement permissionsTabLink;
131
132    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='History']")
133    public WebElement historyTabLink;
134
135    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Manage']")
136    public WebElement manageTabLink;
137
138    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Relations']")
139    public WebElement relationTabLink;
140
141    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Summary']")
142    public WebElement summaryTabLink;
143
144    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Publish']")
145    public WebElement publishTabLink;
146
147    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Comments']")
148    public WebElement commentsTabLink;
149
150    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Forum']")
151    public WebElement forumTabLink;
152
153    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Topic']")
154    public WebElement topicTabLink;
155
156    @Required
157    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']")
158    public WebElement tabsBar;
159
160    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Workflow']")
161    public WebElement workflowLink;
162
163    @Required
164    @FindBy(id = "nxw_userMenuActions_panel")
165    public WebElement userMenuActions;
166
167    @Required
168    @FindBy(linkText = "HOME")
169    public WebElement homePageLink;
170
171    @Required
172    @FindBy(linkText = "SEARCH")
173    public WebElement searchPageLink;
174
175    public DocumentBasePage(WebDriver driver) {
176        super(driver);
177    }
178
179    /**
180     * Check if the title of the current document page is equal to the {@code expectedTitle}.
181     *
182     * @param expectedTitle the expected title
183     */
184    public void checkDocTitle(String expectedTitle) {
185        assertEquals(expectedTitle, getCurrentDocumentTitle());
186    }
187
188    /**
189     * Check if the user is connected by looking for an element with the {@code username} as a class.
190     *
191     * @param username the username
192     * @throws UserNotConnectedException
193     */
194    public void checkUserConnected(String username) throws UserNotConnectedException {
195        try {
196            findElementWithTimeout(By.cssSelector("span." + username));
197        } catch (NoSuchElementException e) {
198            throw new UserNotConnectedException(username);
199        }
200    }
201
202    /**
203     * @since 7.10
204     */
205    public void clickOnDocumentTabLink(WebElement tabLink) {
206        clickOnDocumentTabLink(tabLink, useAjaxTabs());
207    }
208
209    /**
210     * Clicks on given tab element, detecting begin and end of potential ajax request.
211     *
212     * @since 8.1
213     */
214    public void clickOnDocumentTabLink(WebElement tabLink, boolean useAjax) {
215        clickOnTabIfNotSelected("nxw_documentTabs_panel", tabLink, useAjax);
216    }
217
218    public AdminCenterBasePage getAdminCenter() {
219        findElementWaitUntilEnabledAndClick(By.linkText("ADMIN"));
220        return asPage(AdminCenterBasePage.class);
221    }
222
223    /**
224     * Click on the content tab and return the subpage of this page.
225     */
226    public ContentTabSubPage getContentTab() {
227        return getContentTab(ContentTabSubPage.class);
228    }
229
230    public <T> T getContentTab(Class<T> tabClass) {
231        clickOnDocumentTabLink(contentTabLink);
232        return asPage(tabClass);
233    }
234
235    public CollectionContentTabSubPage getCollectionContentTab() {
236        return getContentTab(CollectionContentTabSubPage.class);
237    }
238
239    public ContextualActions getContextualActions() {
240        return asPage(ContextualActions.class);
241    }
242
243    /**
244     * @since 7.3
245     */
246    public List<WebElement> getBlobActions(int index) {
247        return findElementsWithTimeout(By.xpath("(//div[@class='actionsColumn'])[" + (index + 1) + "]//a"));
248    }
249
250    public String getCurrentContributors() {
251        return currentDocumentContributor.getText();
252    }
253
254    public String getCurrentDocumentDescription() {
255        return currentDocumentDescription.getText();
256    }
257
258    public String getCurrentDocumentTitle() {
259        return currentDocumentTitle.getText();
260    }
261
262    public String getCurrentFolderishDescription() {
263        return currentFolderishDescription.getText();
264    }
265
266    public List<String> getCurrentStates() {
267        return findElementsWithTimeout(By.className("sticker")).stream()
268                                                               .map(WebElement::getText)
269                                                               .collect(Collectors.toList());
270    }
271
272    /**
273     * @deprecated since 7.3: use {@link #goToWorkspaces()} instead
274     */
275    @Deprecated
276    public DocumentBasePage getDocumentManagement() {
277        return goToWorkspaces();
278    }
279
280    public EditTabSubPage getEditTab() {
281        return getEditTab(EditTabSubPage.class);
282    }
283
284    /**
285     * @since 8.3
286     */
287    public <T extends EditTabSubPage> T getEditTab(Class<T> tabClass) {
288        clickOnDocumentTabLink(editTabLink);
289        return asPage(tabClass);
290    }
291
292    public FilesTabSubPage getFilesTab() {
293        clickOnDocumentTabLink(filesTabLink);
294        return asPage(FilesTabSubPage.class);
295    }
296
297    public PermissionsSubPage getPermissionsTab() {
298        // not ajaxified
299        clickOnDocumentTabLink(permissionsTabLink, false);
300        return asPage(PermissionsSubPage.class);
301    }
302
303    public HistoryTabSubPage getHistoryTab() {
304        clickOnDocumentTabLink(historyTabLink);
305        return asPage(HistoryTabSubPage.class);
306    }
307
308    public ManageTabSubPage getManageTab() {
309        clickOnDocumentTabLink(manageTabLink);
310        return asPage(ManageTabSubPage.class);
311    }
312
313    public NavigationSubPage getNavigationSubPage() {
314        return asPage(NavigationSubPage.class);
315    }
316
317    public RelationTabSubPage getRelationTab() {
318        clickOnDocumentTabLink(relationTabLink);
319        return asPage(RelationTabSubPage.class);
320    }
321
322    public SummaryTabSubPage getSummaryTab() {
323        clickOnDocumentTabLink(summaryTabLink);
324        return asPage(SummaryTabSubPage.class);
325    }
326
327    /**
328     * @since 8.3
329     */
330    public CommentsTabSubPage getCommentsTab() {
331        clickOnDocumentTabLink(commentsTabLink);
332        return asPage(CommentsTabSubPage.class);
333    }
334
335    /**
336     * @since 8.3
337     */
338    public ForumTabSubPage getForumTab() {
339        clickOnDocumentTabLink(forumTabLink);
340        return asPage(ForumTabSubPage.class);
341    }
342
343    /**
344     * @since 8.3
345     */
346    public TopicTabSubPage getTopicTab() {
347        clickOnDocumentTabLink(topicTabLink);
348        return asPage(TopicTabSubPage.class);
349    }
350
351    /**
352     * @since 8.3
353     */
354    public PublishTabSubPage getPublishTab() {
355        clickOnDocumentTabLink(publishTabLink);
356        return asPage(PublishTabSubPage.class);
357    }
358
359    /**
360     * @since 5.7
361     */
362    public UserHomePage getUserHome() {
363        findElementWaitUntilEnabledAndClick(By.linkText("HOME"));
364        UserHomePage page = asPage(UserHomePage.class);
365        // make sure we're back on the dashboard tab
366        return page.goToDashboard();
367    }
368
369    public WorkflowTabSubPage getWorkflow() {
370        clickOnDocumentTabLink(workflowLink);
371        return asPage(WorkflowTabSubPage.class);
372    }
373
374    /**
375     * For workspace type, the content tab is a bit different.
376     */
377    public WorkspacesContentTabSubPage getWorkspacesContentTab() {
378        clickOnDocumentTabLink(contentTabLink);
379        return asPage(WorkspacesContentTabSubPage.class);
380    }
381
382    public DocumentBasePage goToDocumentByBreadcrumb(String documentTitle) {
383        clickOnBreadcrumbElement(driver, documentTitle);
384        return asPage(DocumentBasePage.class);
385    }
386
387    /**
388     * Makes a breadcrumb element usable, to workaround issues in tests when resolution is too small, see NXP-19710.
389     *
390     * @since 8.3
391     */
392    public static void makeBreadcrumbUsable(WebDriver driver) {
393        log.warn("Removing header elements to make breadcrumb usable");
394        JavascriptExecutor executor = (JavascriptExecutor) driver;
395        // ugly hack for NXP-19710: prevent header elements from hiding breadcrumb links when window is too small
396        String[] ids = { "logolink", "nxw_mainTabs_panel", "nxw_userActions_panel", "nxw_userMenuActions_panel",
397                "nxw_headerSearch_panel" };
398        for (String id : ids) {
399            try {
400                // make sure element is loaded
401                driver.findElement(By.id(id));
402                // remove it
403                executor.executeScript("return document.getElementById('" + id + "').remove()");
404            } catch (NoSuchElementException e) {
405                // ignore
406            }
407        }
408    }
409
410    /**
411     * Clicks on a breadcrumb element.
412     *
413     * @since 8.3
414     */
415    public static void clickOnBreadcrumbElement(WebDriver driver, String documentTitle) {
416        makeBreadcrumbUsable(driver);
417        WebElement breadcrumb = driver.findElement(By.xpath("//form[@id='breadcrumbForm']"));
418        Locator.waitUntilEnabledAndClick(breadcrumb.findElement(By.linkText(documentTitle)));
419    }
420
421    private static final String ADD_TO_COLLECTION_UPPER_ACTION_ID = "nxw_addToCollectionAction_form:nxw_addToCollectionAction_link";
422
423    private static final String ADD_ALL_TO_COLLECTION_ACTION_ID = "document_content_buttons:nxw_addSelectedToCollectionAction_form:nxw_addSelectedToCollectionAction_link";
424
425    @FindBy(id = ADD_TO_COLLECTION_UPPER_ACTION_ID)
426    private WebElement addToCollectionUpperAction;
427
428    @FindBy(id = ADD_ALL_TO_COLLECTION_ACTION_ID)
429    private WebElement addAllToCollectionAction;
430
431    /**
432     * @since 5.9.3
433     */
434    public AddToCollectionForm getAddToCollectionPopup() {
435        AjaxRequestManager arm = new AjaxRequestManager(driver);
436        arm.begin();
437        waitUntilEnabledAndClick(addToCollectionUpperAction);
438        arm.end();
439        WebElement elt = AbstractPage.getFancyBoxContent();
440        return getWebFragment(elt, AddToCollectionForm.class);
441    }
442
443    /**
444     * @since 5.9.3
445     * @deprecated since 9.1 use actions from {@link ContentTabSubPage} instead.
446     */
447    @Deprecated
448    public AddAllToCollectionForm getAddAllToCollectionPopup() {
449        Locator.waitUntilGivenFunctionIgnoring(
450                driver -> StringUtils.isBlank(
451                        driver.findElement(By.id(ADD_ALL_TO_COLLECTION_ACTION_ID)).getAttribute("disabled")),
452                StaleElementReferenceException.class);
453        AjaxRequestManager arm = new AjaxRequestManager(driver);
454        arm.begin();
455        findElementWaitUntilEnabledAndClick(By.id(ADD_ALL_TO_COLLECTION_ACTION_ID));
456        arm.end();
457        WebElement elt = AbstractPage.getFancyBoxContent();
458        return getWebFragment(elt, AddAllToCollectionForm.class);
459    }
460
461    public boolean isAddToCollectionUpperActionAvailable() {
462        try {
463            driver.findElement(By.id(ADD_TO_COLLECTION_UPPER_ACTION_ID));
464            return true;
465        } catch (final NoSuchElementException e) {
466            return false;
467        }
468    }
469
470    /**
471     * @since 5.9.3
472     */
473    public void popupUserMenuActions() {
474        Locator.findElementWaitUntilEnabledAndClick(userMenuActions, By.id("nxw_userMenuActions_dropDownMenu"));
475        Locator.waitUntilGivenFunctionIgnoring(
476                driver -> !userMenuActions.findElement(By.xpath("//ul[@class='actionSubList']"))
477                                          .getAttribute("style")
478                                          .equals("display: none;"),
479                StaleElementReferenceException.class);
480    }
481
482    /**
483     * @since 5.9.3
484     */
485    public DocumentBasePage switchToPersonalWorkspace() {
486        popupUserMenuActions();
487        findElementWaitUntilEnabledAndClick(By.linkText("Personal Workspace"));
488        return asPage(DocumentBasePage.class);
489    }
490
491    /**
492     * @since 5.9.3
493     */
494    public DocumentBasePage switchToDocumentBase() {
495        popupUserMenuActions();
496        findElementWaitUntilEnabledAndClick(By.linkText("Back to Document Base"));
497        return asPage(DocumentBasePage.class);
498    }
499
500    /**
501     * @since 5.9.3
502     */
503    public HomePage goToHomePage() {
504        waitUntilEnabledAndClick(homePageLink);
505        return asPage(HomePage.class);
506    }
507
508    /**
509     * @since 6.0
510     */
511    public SearchPage goToSearchPage() {
512        waitUntilEnabledAndClick(searchPageLink);
513        return asPage(SearchPage.class);
514    }
515
516    /**
517     * @since 7.3
518     */
519    public WorkspaceHomePage goToWorkspaces() {
520        waitUntilEnabledAndClick(documentManagementLink);
521        return asPage(WorkspaceHomePage.class);
522    }
523
524    /**
525     * Returns true if given element representing a main tab is selected in UI.
526     *
527     * @since 7.3
528     */
529    public boolean isMainTabSelected(WebElement tab) {
530        WebElement elt = Locator.findParentTag(tab, "li");
531        String css = elt.getAttribute("class");
532        return css != null && css.contains("selected");
533    }
534
535    /**
536     * Creates a Workspace from this page.
537     *
538     * @param workspaceTitle the workspace title
539     * @param workspaceDescription the workspace description
540     * @return the created Workspace page
541     * @since 8.3
542     */
543    public DocumentBasePage createWorkspace(String workspaceTitle, String workspaceDescription) {
544        // Go to Workspaces
545        DocumentBasePage workspacesPage = getNavigationSubPage().goToDocument(WORKSPACES_TITLE);
546        // Get Workspace creation form page
547        WorkspaceCreationFormPage workspaceCreationFormPage = workspacesPage.getWorkspacesContentTab()
548                                                                            .getWorkspaceCreatePage();
549        // Create Workspace
550        DocumentBasePage workspacePage = workspaceCreationFormPage.createNewWorkspace(workspaceTitle,
551                workspaceDescription);
552        return workspacePage;
553    }
554
555    /**
556     * Creates a Section from this page.
557     *
558     * @param sectionTitle the section title
559     * @param sectionDescription the section description
560     * @return the created Section page
561     * @since 8.3
562     */
563    public DocumentBasePage createSection(String sectionTitle, String sectionDescription) {
564        getNavigationSubPage().goToDocument(Constants.SECTIONS_TITLE);
565        DublinCoreCreationDocumentFormPage sectionCreationPage = asPage(
566                SectionsContentTabSubPage.class).getSectionCreatePage();
567        return sectionCreationPage.createDocument(sectionTitle, sectionDescription);
568    }
569
570    /**
571     * Deletes the Workspace with title {@code workspaceTitle} from this page.
572     *
573     * @param workspaceTitle the workspace title
574     * @since 8.3
575     */
576    public void deleteWorkspace(String workspaceTitle) {
577        // Go to Workspaces
578        DocumentBasePage workspacesPage = getNavigationSubPage().goToDocument(WORKSPACES_TITLE);
579        // Delete the Workspace
580        workspacesPage.getContentTab().removeDocument(workspaceTitle);
581    }
582
583    /**
584     * @since 8.3
585     */
586    public FolderDocumentBasePage createFolder(String folderTitle, String folderDescription) {
587        // Get Folder creation form page
588        FolderCreationFormPage folderCreationFormPage = getContentTab().getDocumentCreatePage(FOLDER_TYPE,
589                FolderCreationFormPage.class);
590        // Create Folder
591        FolderDocumentBasePage folderPage = folderCreationFormPage.createFolderDocument(folderTitle, folderDescription);
592        return folderPage;
593    }
594
595    /**
596     * Creates a File from this page.
597     *
598     * @param fileTitle the file title
599     * @param fileDescription the file description
600     * @param uploadBlob true if a blob needs to be uploaded (temporary file created for this purpose)
601     * @param filePrefix the file prefix
602     * @param fileSuffix the file suffix
603     * @param fileContent the file content
604     * @return the created File page
605     * @throws IOException if temporary file creation fails
606     * @since 8.3
607     */
608    public FileDocumentBasePage createFile(String fileTitle, String fileDescription, boolean uploadBlob,
609            String filePrefix, String fileSuffix, String fileContent) throws IOException {
610        // Get File creation form page
611        FileCreationFormPage fileCreationFormPage = getContentTab().getDocumentCreatePage(FILE_TYPE,
612                FileCreationFormPage.class);
613        // Create File
614        FileDocumentBasePage filePage = fileCreationFormPage.createFileDocument(fileTitle, fileDescription, uploadBlob,
615                filePrefix, fileSuffix, fileDescription);
616        return filePage;
617    }
618
619    /**
620     * Creates a Collections container from this page.
621     *
622     * @param collectionsTitle the Collections container title
623     * @param fileDescription the collections description
624     * @return the created Collections page
625     * @since 8.3
626     */
627    public DocumentBasePage createCollections(String collectionsTitle, String fileDescription) {
628        DublinCoreCreationDocumentFormPage dublinCoreDocumentFormPage = getContentTab().getDocumentCreatePage(
629                "Collections", DublinCoreCreationDocumentFormPage.class);
630        // Create File
631        DocumentBasePage documentBasePage = dublinCoreDocumentFormPage.createDocument(collectionsTitle,
632                fileDescription);
633        return documentBasePage;
634    }
635
636    /**
637     * Creates a Collection from this page.
638     *
639     * @param collectionsTitle the Collections container title
640     * @param fileDescription the collection description
641     * @return the created Collections page
642     * @since 8.3
643     */
644    public CollectionContentTabSubPage createCollection(String collectionsTitle, String fileDescription) {
645        CollectionCreationFormPage collectionCreationFormPage = getContentTab().getDocumentCreatePage("Collection",
646                CollectionCreationFormPage.class);
647        // Create File
648        CollectionContentTabSubPage documentBasePage = collectionCreationFormPage.createDocument(collectionsTitle,
649                fileDescription);
650        return documentBasePage;
651    }
652
653    /**
654     * Creates a Note from this page.
655     *
656     * @param noteTitle the note title
657     * @param noteDescription the note description
658     * @param defineNote true if the content of the note needs to be defined
659     * @param noteContent the content of the note
660     * @return the created note page.
661     * @throws IOException
662     * @since 8.3
663     */
664    public NoteDocumentBasePage createNote(String noteTitle, String noteDescription, boolean defineNote,
665            String noteContent) throws IOException {
666        // Get the Note creation form
667        NoteCreationFormPage noteCreationPage = getContentTab().getDocumentCreatePage(NOTE_TYPE,
668                NoteCreationFormPage.class);
669        // Create a Note
670        NoteDocumentBasePage notePage = noteCreationPage.createNoteDocument(noteTitle, noteDescription, defineNote,
671                noteContent);
672        return notePage;
673    }
674
675    /**
676     * Creates a forum on this page.
677     *
678     * @param forumTitle the forum title
679     * @param forumDescription the forum description
680     * @return the created forum page
681     * @since 8.3
682     */
683    public ForumTabSubPage createForum(String forumTitle, String forumDescription) {
684        // Get a Forum creation form
685        ForumCreationFormPage forumCreationFormPage = getContentTab().getDocumentCreatePage(FORUM_TYPE,
686                ForumCreationFormPage.class);
687        // Create a Forum
688        ForumTabSubPage forumPage = forumCreationFormPage.createForumDocument(forumTitle, forumDescription);
689        return forumPage;
690    }
691
692    /**
693     * @since 8.3
694     */
695    public boolean hasNewRelationLink() {
696        return getRelationTab().hasNewRelationLink();
697    }
698
699    /**
700     * @since 8.3
701     */
702    public boolean hasFilesTab() {
703        try {
704            return getFilesTab() != null;
705        } catch (NoSuchElementException e) {
706            return false;
707        }
708    }
709
710    /**
711     * @since 8.3
712     */
713    public boolean hasNewButton(boolean isSection) {
714        if (isSection) {
715            return getContentTab(SectionContentTabSubPage.class).hasNewButton();
716        }
717        return getContentTab().hasNewButton();
718    }
719
720    /**
721     * @since 8.3
722     */
723    public boolean hasEditTab() {
724        try {
725            return getEditTab() != null;
726        } catch (NoSuchElementException e) {
727            return false;
728        }
729    }
730
731    /**
732     * @since 8.3
733     */
734    public boolean hasNewPermissionsButton() {
735        return getPermissionsTab().hasNewPermissionButton();
736    }
737
738    /**
739     * @since 8.3
740     */
741    public boolean hasManageTab() {
742        try {
743            return getManageTab() != null;
744        } catch (NoSuchElementException e) {
745            return false;
746        }
747    }
748
749}